 All right. Hello everyone. Welcome back. This is a somewhat more informal stream This is not gonna we're not gonna tackle as any particularly super hard technical topics is really just Me building something interesting. Maybe I don't know in in rust then you get to just see some non super technical coding for once The basic idea and I've had this for a little while as I want to I wanted to have a way for people to Give opinions on what topics to cover in upcoming streams and There are a bunch of sites out there to like let people do votes and traditionally what I've done is use just the Twitter polls and That works fine But it's a little bit annoying that we keep having to go through the same sort of vote options And so I've been sort of in the back of my head thinking about how we might want to do this and there's been a lot of discussion about like how voting works in the US and one of the sort of proposed solutions that have come up is this idea of ranked voting and And I have a drawing pad now. I'm very excited and So for the Tokyo stream that we're doing this Saturday because it's more of a conceptual stream I figured it'd be useful to be able to draw things. I'm gonna. Oh, that's very bright I don't know if I can do anything about that. Oh, maybe I can actually How about this? How about we fill this with black and we draw with white? like This one Fill with that one There we go, and then in theory, let's see if this works in theory. I can draw here now Great. All right. So is that legible like roughly? Oh, this is just this is just gimp. There's nothing pretty pretty interesting But I've got one of these it's like a little little drawing pad and a pen And I'm not gonna write text here because my handwriting is terrible But but what I wanted to do was basically give you an idea of how this works So the idea in in ranked choice voting is everyone fills out. Everyone is given like a form Where you are told to rank your candidates So imagine here that we have five ballots. Wow drawing like this is really hard Okay, so we're gonna be voting on say choices a b c and d right so everyone is gonna rank They're the choices that they would like to see and they're gonna rank them basically in order. Oh Legible, okay, good. So the idea is let's say my let's say that this is I'm not gonna name them because that's annoying But this voter votes for a Then b then c then d this person votes for a and just a so you don't have to do Exhaustive listing think of these is so these could be like candidates for an election in my case These would be IDs for streams, right? So this is a streaming ID a streaming ID b streaming ID c and streaming ID So the first person voted for all of them in in sort of alphabetical order This person voted just for a and for nothing else this person Let's say votes for b and then a as a secondary this person votes for b and then C and then d and then this person votes for C and then a Okay, so the idea of rank choice voting is that you want to get some candidate There are many versions of this. I'm gonna explain a very straightforward one I Recommend you look this up and we could be if you're interested the basic idea is that you're gonna look at all of like everyone's first choice And you're gonna see if anyone has a majority of the votes So in this case both of these have a both of these have b and this guy is C, right? And so no one has a majority no one has more than half the votes and then what you're gonna do is you're gonna eliminate the The candidate that got the fewest votes So in this case, I guess you eliminate d. I actually don't know whether you eliminate d in this case But let's say that you eliminate d So you eliminate the candidate who got the fewest votes and then you do it again, right? So now We check whether or not as a majority obviously no one does so then we eliminate candidate C And then what you do is you always look at whoever now is the primary candidate for each ballot So in this case this person is still voting for a this person still voting for a because a is still in the race These people both voting for B this person they cannot vote for C So their vote is now for a so now a has three out of five and therefore a wins the election Right. So this in and of itself is an interesting voting strategy But the reason specifically why I wanted to use this for stream ideas is what you can do now is imagine that We now Now I do stream a and so a is no longer an option right a has gone away What you can do now is without anyone doing any more votes I can rerun the election with a removed I Remove a from everyone's votes. So I pretend like a is not there Right. C is now back here, right? So this now does say C again This now does say D and this now does say D But a is gone. And so now I just like people can still vote if they want and like change orders I could maybe add alternatives, but in general all the old votes are still there so I still roughly know people's preferences and so what's now going to happen is I rerun the election and This time B wins right because this vote is now for B This vote is now for B and this vote is now for B And so now I know that I should do stream B So then I get rid of B and then I run the election again with be removed and This time C wins. So now I do see of course in this kind of stupid in this particular example Like they happen to be in order, but that does not necessarily be the case Right. So if this was B instead of a then B would have won the first election So the basic the basic reason I want to do this is because I can I can have people not have to vote every time on The same options they've been given before but instead just say rang these candidates and pick which whichever ones you care about And then the appropriate streams will happen. There's no like voting strategy or anything And then of course I can extend this with adding new options so people can add them to the list of things that they want to vote for So I think this is pretty cool So that's basically what I'm going to build is there a question here a little bit like the Australian election voting system Yeah, maybe I don't know what they use in Australia. I know that this is something that a couple of US states have started doing this now So No, no Switching between pen and mouse is weird okay, so Basically the interface I want I want this to be super simple, right? So we're gonna probably let's say we have three views We might not even have three views From Russia cool. Yeah, it's a really interesting voting system. There's a great YouTube video by someone called CP gray you just search for Something great you search for like gray Ranked choice voting. Yeah, there's a really good video that explains the principles behind this better than I can do in this video But so let's okay, so it's not entirely straight lines But imagine that these are sort of the three different pages that are gonna be in this application the first page Because I don't I don't care about security here. I don't think people are gonna impersonate one another and if they do I don't really care So the basic premise I want is something like Maybe you don't even want that but I was imagining something like the first screen is just a text field Where you can input a unique and unique identifier and it shows you Maybe the set of upcoming stream IDs Ordered by the current winners, or maybe it just shows you the current winner I don't know yet. We could look at that when we get there The idea is that if you give some unique ID Then what you're gonna be presented with is a list of all the stream options Probably in random order not terribly important and the idea is that all of these are draggable right and so what you do is you just sort of drag them into the order you want to vote for these stream IDs in and Then whatever order you have at the end is the like it's just gonna save all the time and basically continuously run the election and so there might not be a third screen in fact and If you later come back and you want to change your votes or new things have been added you just go back to the page You fill in the same unique identifier. You get the same list you reorder Because you should be allowed in rank voice voting to say like I don't care about these options Like I don't want to vote for them. We might need to have something like Sort of a barrier saying I don't care about anything below and anything that's underneath that in the list Will automatically be considered you're not voting for this one Right, so you can you could imagine that this is also draggable, right? You could drag this further up and then any choice below that is basically just going to go away So I don't think there's a third view actually Now of course, this is all sorts of broken from a security perspective because like people can just manufacture new IDs and all that stuff But the goal of this is not to build an election system It's just I just want some way for people who are watching to like be able to say what they care about If someone like screws with it, I will probably do something to make it better But let's just start out with something super simple where there just needs to be a possibility to have multiple users, right? Okay, so that's the basic idea. There's the basic idea makes sense I don't think it's particularly complicated, but it's useful to just sort of do a double check I'm gonna put this aside now If I have to draw more then I will draw more And as we go like I haven't implemented this before it's gonna be a bunch of web programming So like who knows what they're gonna be interesting, but we'll see See Right We're gonna be using rocket for this is the idea so rocket is this um, it's a Web framework for Russ that was written a little while ago And it has this peculiar design decision that they want to always target nightly So they can give it like the most flexible API so it's not intended to be stable But I don't really care. I just want something that's easy to Easy to write with um, and they have a bunch of really good examples. So I'm actually just gonna go here Examples And they have one that's like I think they have one that's basically a database type stuff Actually, it's used to do list To do lists are great as a starting point because they usually have a database of some kind And they usually have like sessions of some kind Why not actics web Yeah, actics web is actually you need to write more code than you do in rocket Because you basically need everything needs to be written as a service And I don't care enough to write everything as a service here. It probably could. Oh, I don't particularly care Um Are you using rocket zero four or three six? No Probably zero four. Why not? Let's uh, let's be bleeding edge. Shall we? So we'll probably use this For database, I think my guess is this example uses diesel too. We're gonna be using diesel for the database backend So diesel is this really handy crate for interacting with databases Uh, it has really nice apis. You can write structured queries in some sense We're gonna need very little of this because the the database here is really stupid, right? It's just like a user's table A stream id's table and a vote table But we'll see what it is Where it gets really interesting is someone wrote this crate, but they actually asked me to review for the For the open source contribution stream Which is a rank choice instant runoff library So rank choice is the thing we looked at instant runoff the idea If I remember correctly is basically that you do the revote immediately um So we're gonna Basically use this crate the if I remember correctly the api for this is super super simple There's a run election method you give an iterator of iterators. So the outer iterator is uh Each person basically every ballot it yields a ballot These should probably be named better So each of the items from the the first the outer iterator gives you a ballot And then each ballot is an iterator over the votes and then it gives you back who won the vote And for the drag and drop stuff, this is really handy library called sortable That basically has no dependencies and it gives you a drag and drop list So that's the plan Tower is also a new crate for the web. So tower tower is interesting I've been playing around with tower a bunch and towers you can think of it more as Sort of higher level abstractions for writing clients and servers. It is not Really a web framework yet, but I think the idea is to try to get there There's also tide which is being developed by erin turin And so that might have some promise too, but I don't know that it's in a state where we can really use it The reason I chose rocket is really because I I just want something that works like in some sense The purpose of this is not to dive deep into sort of rust technical issues But rather go we're going to build something that just uses a very straightforward well maintained library That has good documentation. It's easy to get get up and running with quickly Glad to see another stream. Yeah, so am I it's uh, it's been a while It's been a lot of stuff going on, but now we get two very quickly after one another All right, so we're going to use sortable. Um, I guess what we'll have to do is start out with a rocket project I think we're just going to start out with this to do example Let's just look at what this looks like before we copy it all in. Let's seem successive Um, yeah, okay. So this does use diesel, which is basically what we want Um diesel has this notion of migrations So the idea of a migration is you can specify whenever your Database schema changes you do a migration that can be reverted so that you can downgrade your database if you want to We'll probably use it the in some sense the less I have to change from this example the better And then there's this notion in rocket that you can annotate things so, um Every function here is a is a request or a route So in this case if you go to Is there a where's get slash Here, okay, so this is if you just get the the where you're running the server slash and you do a get request This method is going to be invoked. Um, and One of the ways in which rocket is neat is it looks at the arguments to that function to determine what its dependencies are So the way to read this is Index rendering the index is going to require that you have an You have an optional flash message. You may or may not have a flash message thing And you have a db con and rocket will do the necessary thing to essentially acquire those resources Uh, so in rk and then it returns basically something that is renderable Uh, so that might just be a template rendering, which is probably what we'll use although our templates are also going to be very straightforward um So as I get right, so so all of these have access to the database through this con object And we will do something similar where we're going to use con to Both extract the current vote results and to Insert new new votes and new users Okay, so this seems like a decent starting point. I sort of want to extract just this Can I just like download it do I actually have to clone it probably Uh, let's clone this out and then let's uh Cargo actually make their no get in it Um, what are we going to call this? Voters that's funny Sure voters voters it is Probably terrible name Um, and then we're going to copy all of the stuff from rocket examples to do to here Oh, there's no get ignore That's interesting You can just do this It's probably has a bunch of stuff we don't care about maybe Sure It's uh, get rid of this Don't need this And we're going to cargo check just to see this actually works Probably doesn't because we need One we're not going to publish that's fine. We don't have a workspace. We depend on rocket Is um Rocket zero four up. Yeah, great zero four Uh, we probably depend on diesel I don't know if I care about these migrations. Can I use diesel without migrations? I'll be my guess but Uh Oh diesel cli That's what I'm saying. I don't really want to diesel cli Oh, I see So you don't actually need the cli It just generates some stuff for you Interesting I wanted to not do any of these things, but I guess we could probably do it fine Uh, so let's do here Cargo install diesel cli have that run in the background um Right, so we're we're basically going to get rid of the the migration stuff because I don't think it's important Uh We don't need log Don't need any of the dev dependencies I don't know if we'll need rocket country It's a good question. What is rocket country? country Yeah, okay Quick start that's unhelpful Uh, sure we can list that that seems fine It doesn't look like this really needs So I guess let's get rid of that. Oh, but it has things like templates. So that's probably why Hmm, I don't know where that comes from rocket How weird Well, we want that uh, in fact, we probably want it here But we want the version to be that version And sure we'll have the those dependencies whatever the to-do application is using is probably what we want as well Um Well, let's see back to diesel did this install finish Oh Apparently oh, actually I want clients. I guess I don't care about the server Actually, sure. I just want lived maria db plant. So I was it was complaining that it couldn't find, uh L my sequel client, right? So the the library my sequel client Which we do want now see what that gives us Try that again Back to this there's probably a bunch of stuff here. We don't need would be my guess Um But we're just gonna keep it in there for now All right. So now we have diesel Is here we'll go into voters as well um Oh, this is all using postgres which in some sense. I don't want let's do Diesel setup and see what that gives us because we can remove migrations uh We can remove this db directory And we're gonna do diesel Sure database url Uh, it's gonna be sequel light maybe Uh db dot sequel is not huh diesel So I don't actually want to run a database Because it's annoying So the question is what do I have to do to do setup with that? Oh, you need I feel like that's not true So the alternative is that we sort of scrap the migrations entirely and we just manually create the database That seems just as fine. Uh, so I have the sqlite there. So let's just do Uh, oh, it's diesel dot toml Maybe this will help us I feel like this is far more stuff that I need for this. So we're gonna scrap that Maybe we'll add it back later for now this like we're not expecting this database to grow much It's gonna be a very small application Uh, what is bootstrap? Nope get rid of that Uh, let's get rid of the readme because we're not going to need it Uh rocket dot toml Sure So that says something about where the database lives. Okay, so this is the file we're going to have to make Right. Um, so we're going to do something like this Uh, and in particular what we want is I guess here Schema dot We're gonna have the simplest schema anyone has ever seen in particular We're gonna have a table called users and in users What are we gonna have we're gonna have Something like id which is going to be a text field. It's also going to be primary key. No No id is going to be auto increment Integer auto increment Maybe it's like this in the sqlite I don't remember Uh, and then we're going to have something like a username Which is this like unique identifier the user does Eventually we'll probably get out of password here, but uh, it's going to be a text not no unique Those are all the things that are going to be in users We're going to have something like Items which are they're going to be the things that you can vote on that's also going to be Have an id and in addition it's going to have something like a title probably And it's going to have a body And then we're going to have votes So remember that in uh rank choice voting every user can vote for multiple things So what we actually need to store is a user id Which is going to be an integer not at all It's going to be an item id which is going to be an integer not an all and it's going to be something like an order Which I probably can't escape it, but uh Ordinal So the idea is that these are all the things that the user chose to vote for An ordinal gives the order that they gave for those things Hmm We do want though A unique I don't know how you do this in sqlite Uh, we want a unique index on user id item id, right? So Uh, a given user cannot Place the same item id multiple times on their ballot. Sure. Maybe there maybe there Uh, no that seems like no Can I make this be a unique index? I wonder because uh, we're going to do I guess we're not really going to do lookups on this So it probably doesn't matter a constraint is probably fine Unique constraint we're going to do is going to be user id item id Now in order to check In order to check that it might actually need uh, we might have to do an index. Otherwise it's going to be super slow But let's just punt that problem as well. Um Don't you need to rep to reference to user id as in foreign key So sqlite actually doesn't enforce foreign keys. Also keep in mind Foreign key is really just a constraint the database places saying that actually Maybe it might support that last time I checked it not but sqlite foreign key Uh, a foreign key is really just a constraint saying that for any value you put in this field a value must exist in this other field Which gives you Useful things like if you delete a user you can also say to delete all of their votes But in general sqlite has had pretty poor foreign key support that might have changed Yeah, enforces exists So let's see Sure foreign key user id References users id Seems fine. Can I declare multiple ones? Do I need commas between them? I don't know Uh items Is that what you meant, uh ghost? I think those are basically the things we care about Oh, I guess this should be No And I don't know if you need to let me do that. I guess we're about to find out So we're gonna do this and then we're gonna import schema dot sql If not like that my guess is that it requires something like this this maybe not happy about those Ah Drop table users As you can tell this is a very sophisticated application setup Great. So now if we try to open this database Tables and notice that There is nothing in any of them, but they do have the right columns at least in theory Yeah, that's what you meant. Okay, great. So now we have a table setup and if I remember correctly diesel basically wants you to um Have a programmatic representation of your tables I don't know exactly how it does that Yeah, the schema and models, which is basically we're gonna have to transcribe our screen schema into a rust All right, so we're gonna go to main what there are some other files in source that I don't want to be there source Tests I'm not gonna have any tests might add tests eventually. I don't know. Uh, we're also probably not gonna have a What's in this tasks table? Right. So this has the the diesel schema Uh, in our case the diesel scheme, of course, is going to be very different So we're gonna move source Uh tasks to be source Schema.rs right, um Oh, I just have schema and model. Oh, I see here. They're really just all put into one, which is probably all we need um, so we're gonna have a mod schema and Uh, we don't have tasks. We have users right So this is where the other schema file comes in handy We have users. They have an id which is an integer And they have a username as text Uh, I think you can declare multiple of these So we're gonna have table votes I guess let's do them in order Uh items has title and body And finally we have votes Which has a user id item id and ordinal All the which are integers Uh, in school we had class about how to structure the database Yeah, I mean, so if you think about it, we have really structured the database the correct way. It's more You're sort of supposed to do this in the style of diesel will manage bringing up and down your schema and sort of Auto generating these types and I just decided to do it manually In part because it's not important for this application This application is not going to grow and if it does it should be rewritten It's more I just want something that is up and running because this is a very straightforward application, right? um, I'm hoping What's this thing It's probably a primary key of some kind. Okay, so My guess would be that whatever goes in here That's like a primary key. So we have a primary key. That's great I don't know what we do for this the table macro. Ha um Yeah, that's fine That's fine. We don't particularly care about that I guess we declared all these to be text didn't we so let's just keep them as text. That seems fine Uh, you may specify a primary key if it's other than id Okay, great. So it is just assumes that id is the primary key. Uh, that's not true here Uh, list all the columns in the primary key. Great user id item id What is our example is like basically the same as ours? Uh, no, that's all fine Because you could add some documentation. I don't think it's important SQL name that's all right So what that gives us is this module called running port users I don't know what this other import is What I'm basically doing here is just taking the example and rewriting it into what we're doing Right, uh, so we have users items and votes And then I think the the idea in diesel is that you have sort of your schema representation And then you have models which are your rust um Sort of representation of what's in the database Uh, so if you look If you look at the diesel configure not this one Right, so post here for example is the the rust representation of what's in the database Typically this Right, so normally diesel setup will generate this files for us. Um, we just happen to have written manually Um And I guess let's also write this model So we're gonna have item Can be queryable sure Uh, and remember item really just has title and body You could have published Uh, we should have finished or done maybe That's a good point so for any item we need to be able to record the fact that We need to be able to record the fact that a given stream is finished so that we don't count it anymore, right Uh, and here arguably there should be an index on done because we're generally just going to query for items that are not done But we're gonna ignore that too. Okay item Uh, id is going to be i32 that seems fine title body and done Uh, and I guess we also have user Which is just id and username And we finally have votes So that's going to be a vote that's going to have a user id It's going to have an item id We probably here want to do something like implement Ordering for vote and order by ordinal Okay, that's fine. So I think that's all the types we need and then it says Okay, do some stuff to establish the database connection We probably here want This To be insertable Probably also is things like debug and clone or handy Don't know why it has to be serialized Items, I think we only want to be queryable from the application. They probably should be debug though I don't think we even needed to be cloned Vote should be queryable Insertable debug That might be important actually Right because we're gonna add new We're gonna add new votes as we go I don't know what this dsl Leaded and oh, I see what they did here So Or is the example from rocket? If you look at main here, sorry if you look at task Notice it has a field called completed Uh, I think what this macro generates Is this dsl sub module And it generates one Function that is called the same name as the table which gives you all the things And for any given field that generates a function that lets you fetch by that field Right, so that's why this all calls this all tasks, right Um where it's completed used I wonder see completed being used anywhere here Yeah, I don't think that's being used All right, but that does mean that what we probably want out of this is Uh, we want the ability to get all votes Right That's probably the only one we need actually Uh We don't oh, we do probably because we um singularize this is now going to be the table is called votes not vote This table is called items not item and this is called users Uh This in rust just looks so nice. Yeah, I know it looks pretty neat, right? Uh, it was in an argument. What was in an argument? Sorry. Oh, was it I was task was this in an argument somewhere? Oh, yeah, you're right Set task completed Oh This is naming that column If you only want to update one field I don't think we ever want to do that though So I don't think we actually need that We never need to be able to change the just one value of a given field because I think for votes We're probably just going to clear all the users votes and then add them again Uh For item we're only going to read them and for user We're only ever going to insert and look up. I think I think we'll probably want something like an index on username Uh Fine fine fine fine There are some indices we just very obviously need here Oh, hey, look at that create unique index Fantastic Give me this So for users, we're going to want create unique index Uh, username On users username Can I also delete index? Actually, it's fine Uh Here There's already going to be one. I think on the primary key just always Do I really I feel like this is not the website I want to use for this I want the real sqlite reference. Here we go Table of contents This needs jobscript too. Why does everything need in like jobscript these days? We're disappointing Uh fine documentation Programming no overview No also not really what I wanted Features Features auto increment Uh It's usually not needed Uh in sqlite a column of the type integer parameter key It's an alias for the row id Oh, I mean, I don't think we really care if they're reused So it sounds like what you're telling me is this should be Integer primary key instead of auto increment. That's fine Uh, and I guess row id there's always an index on Okay, that seems fine Uh, we don't that's not important. Um, well, we do care about why is this setup of the site so stupid? um I guess indexes Right that's fine uh Okay, so ids are basically automatically indexed I think for items we only care about ids. So that's fine for votes We probably want a unique index On User id item id so the reason we want this index is so that this constraint can be easily checked Um, I don't know if we need both actually the index might be sufficient So that's fine. And then we also probably want an index on Um, so this is going to be something like valid On votes by user id and ordinal right, so remember, um When we're when we're running the election what we really want is for every user Step through all of their votes Which is basically doing a select order by user id ordinal And then sort of subdividing it by by user we're grouping by user might end up using iter tools for this actually It has a nice group by function. Uh, and so having this index allows us to Is the efficiently do that that walk at least I think Uh, it depends a little bit on what create index does Use create index great Didn't get sort order, right? So I think We want something like user id ascending ordinal ascending ds ascending yes great Right, so this is going to let us efficiently do that query Although at this At the same time, I might not matter. We're just going to query We're basically going to extract all the votes for anything that is not done So I guess the ordering is handy in that sense regardless Uh, that's fine Okay, so we have a new schema But we didn't really change anything apart from add done here as a bool Right, apart from that everything else is the same Uh going back to diesel Okay, what else does this have is there anything here we might want? Uh, this is from form business Which I guess is Uh Oh What is to do in this example To do is not something they have at a table. Oh, I see so, um, right So this is going to be something like new user Which is just going to have a username Right, so this is you're going to have a form that just gives a new user And similarly we're also going to have something like A new vote I don't think we're going to have a new vote actually I think we're going to add all of those Manually and then these are some convenience things and for us, uh, I don't I think the only convenience things we really want is vote Uh Run election and what that's going to do is it's going to do All the tasks order Well, not all tasks all votes Uh order by Hmm, I guess here we're going to have to resort to Figuring out what diesel actually does under the hood because we want to do a double order by right We want to order by Both the user ID and ordinal and we want to do a join with item to make sure that we're only checking votes for things that are not done Oh Oh, that's awkward fine diesel docs Um, so for I guess DSL is what we're going to get back Maybe not Query builder. See this is the problem with deciding to just uh sort of add hawket from something existing So I have no idea what any I think it's like a query builder No query Hmm, where can I find order please what that's false Let's try that again Uh Query DSL methods, right? So my guess is whatever we get back Yeah, I exactly. So this is what we're gonna get and I guess what we want is We want an inner join Against what the right-hand side here What is that? That looks awful joinable Interesting. So there's clearly some stuff in this that we might want to actually figure out Um, who? I don't think we care about the overhead of that. That's fine I just want to get back to where it lets us where can I define relationships more guides? Uh, schema in depth. Perfect Okay, that's fine. That's fine. That's fine Don't care about any of these things for now Specifically what I want to be able to declare Is the relationships between these tables Composing fine We'll do about it the other way, which is diesel. Uh, what is a joinable please? Joinable Aha Interesting. Okay, so we're gonna say This Go inside schema. No, okay. So we're gonna say that um You can join votes with items Parent table is the table with the primary key Child table is the table with the foreign key The foreign key would be post Dot user ID Right, but how does it oh, I see it just assumes that the other one is ID. Okay. So in this case Uh, that is going to be item ID and then we're going to have the same for votes to users using user ID Great. I think what that means Is that we can now for a run election for inner join remember we saw here Uh, you can pass that table directly Okay, so I think what that means is here we can just pass, uh Uh items And then what we want Right, so that's not important It's gonna give us the With implicit on clause, right. So just inner join points, right. So this is exactly the same thing we do What is that? What is this monster allow to appear in same query? Uh, sure, I don't know why this is necessary, but I believe it Uh, we're allowing users items and Does it give a warning for why you shouldn't do this? Okay, fine Uh, great. So it's saying then we can just do inner join that Um, I guess we will probably want to select at some point What is name and title here? Oh, they're the column references from the schema module Um, that's fine. We sort of want to wear here those somewhere Uh, I guess filter Right, right because we want to filter out things that are done Right, so we're going to do I guess this is where we'll do something like Uh, where is this right? So we want votes as all votes Uh, we want Oh, actually that's fine And we want items, uh What's the column of item done? as Item done And then we want something down here along the lines of filter by item done is equal to false And then the question is for this order by Uh, if I want to order by multiple things, what do I do? Oh, I just give it a tuple great Um, and I guess here, I guess we'll want votes This we'll want a user ID And item and ordinal Because now we'll do something like we'll order by User ID ascending and ordinal dot ascending. I don't know what this load is going to do Oh, that's just going to give us right. We want to load these as votes. I have no idea if that's going to work What does load do that's another good question. Uh, what did all of these give us back? Something that we can eventually call load on right So what does load do really care about limit Run query dsl Right, right. So this is going to collect into a vector. Which is not really what I want But it might be the only way to Aw, that's a little sad You really have to collect into a vector Fine, I guess we can survive. Uh, so we wanted to collect all of the votes This is going to give us a vector of vote Right And then we're going to run the election on this but in order to run the election We need to group by user right we want to count each user's Thing separately each user's ballot separately So we'll use iter tools Um, so iter tools. This is a really handy crate for For operating on iterators and doing fancy things So we'll do something like iter tools Is equal to 0.7 This we're not going to do this we're not going to need. I don't know. Why serdi. Oh Serdi is here so you can send jason back and forth Sure, that might be oh, that's why it's serialize I guess this we do want to be serialized so that we can Send it to the client to show what the current items are. That's true Uh, this is going to be mod Schema which is silly, but we're going to have schema schema um And I guess this we want to we want to include schema user item vote And new user I guess we'll probably do something like we're going to want these other like inserts and deletes I guess this is going to be something like save ballot It's going to take some kind of iterator or something. We'll have to figure that out later um So back to iter tools we're going to add here an extern for that There are tools Notice that we're just like cannibalizing the existing to do example, right? Writing this a lot of the code that's below here is probably just going to go away Use iter tools So what this gives us is this trait Super oh Straight function No, I don't think any of those first Specifically what we want here is group group by group by Uh consecutive elements that map to the same key are assigned to the same group The groups are consumed in order Uh, then group by uses no allocations So we've already assured that that's going to be the case right Remember how we sort by user id and then by ordinal So we know that the the collection we provide to iter tools is already ordered by the group by columns It needs allocations only if several group iterators are alive at the same time, which will not be the case This type influence into iterators not Okay That's fine So what we have down here, so these are the votes Uh, we're going to do votes dot iter dot group by And we're going to group by for each vote We're going to group by the votes User id right, I don't know you get fields Probably down here somewhere Oh, it's just dot That's handy Right Looks like that's all that's needed Great, so we're just going to do I guess v dot ordinal So we're going to group by so that gives us back something that is an iterator and If everything goes according to plan then All we need to invoke now is rcir There's no way now all of this is going to work initially, but Hey, we'll see what happens extern create rcir And up here, I guess we're going to use rcir run an election Actually just use rcir Uh, and this is going to return Uh an rcir is an election result Of and this is going to do rcir run an election There are probably types that are not going to work out here This is going to have to take some type Who knows what it's going to do Let's just have this be true for now Or just have it return nothing from now All of this we don't know what we're going to do with yet, so we're just going to comment it out Back here There are a bunch of these things I don't know what are Migrations we know we're going to go away The sql lite database connection is still going to be there Context and we're free of what context is later All of these routes we don't need in the beginning. Let's just start by focusing on we want slash to work There aren't going to be flash messages in our application. It's very straightforward Rendering the index is just going to be a matter of rendering the index Oh context would you provide to the template? So And for that I guess the context is really just going to be Can this be an enum? I feel like this can probably be an enum Uh, it does not need to be Let's just not do references and use strings everywhere. It's fine. Um The context is going to be something like election Uh winner Which is going to be a rcrr vote result vote and a What else is there going to be? Oh, I guess streams or items, right? Which is going to be item Vecco by them. Oh, I guess we will need something like impulse item Um It's going to take a sql light connection and give you back a beck of item And this is really just going to be all items items as all items And so this is going to be all items dot I guess we don't even really care about the order of the items So we're just going to dot load item It's very sophisticated code this here Um, there aren't really going to be errors for a context Uh, it's going to be none of that This is going to be a new all you're going to be able to do is construct a new context And the things it's going to give you is a winner Which is going to be vote run election So notice that this reruns the election for every user. So this is highly inefficient We might want to do some caching to avoid that And in fact, we can probably do that pretty easily right because this is just running a single process server So we could totally just like keep an arc mutex of the current election results Seems fine And items are going to be Item all great This Is now just going to be context new Give in the con And that's all you need Uh We're not going to do any database migrations So that's fine. It means that flash message goes away I guess we might want things like flash for if the username is already Oh, we don't use a name already taken just logs you in great um Fantastic Okay, so we're going to attach this db connection that has to be a So rocket has this notion of fairings, which are basically resources that you can pass in as these kind of arguments to functions And they will be auto created. So we want to say that database connections is one just thing We want to use slash to serve static files from the static directory CSS and images might not even have any of those Slash is just going to have the index route. We don't have any of these other ones yet And we want the template fairings so that we can run templates Uh, we're about to find out Sure run this Probably not going to compile But we're about to find out Ooh panicked Oh, I guess uh It's the basic idea Or this is like basic application setup seem somewhat reasonable I mean, it's it's terrible in all sorts of ways, but does it roughly make sense? Ooh I did something weird schema 987 What did I do? Oh How about now I'm 30 this Because that's a struct Tema 46 This Well, that's weird We just copied over the main from The example So why is this okay here, but it's not okay in our code seems dubious But sure Who knows do that as well sure Uh, it's complaints about a lot of things Interesting So we've done something weird with this joint business. We just perhaps not terribly surprising Posts colon colon table. Oh interesting. Okay, so for This business down here The inner join is going to be with self schema Uh Items table maybe yep apparently Oh, this isn't vote result. This is uh election results What else are we broken? so RCR is a little bit annoying in that if you look at the interface for run election, uh, it Always operates on references Which is not really what we want Because it's pretty annoying to work with I guess because in our case all of the Items are owned that we give it Well sort of I also don't know. What does it require for the type it runs the election on? That it was eek and hash again, that's also something we're gonna have to deal with Um, oh wait, this group should be by user ID And then I guess we're also going to do something like We sort of want to map this group by Yeah, we're gonna have to do something weird here. I'm not entirely sure what yet basically So the run election is over an iterator of iterators of Basically things that are votes they get compared and so we need to map out just the item ID of every vote because that's really what the ballot is Um, it's also a little bit annoying that all of this has to operate on references Would have liked for that not to be the case So here's what they could do. We could just copy this code. It's not very long Uh But I sort of don't really want to do that I wonder if we could say that these are static. No, I can't do that either. Okay, fine Let's just say that the winner is a vote Sorry, and the winner is an item. It's not a vote. What am I talking about? The winner is an item Yeah, some stream ID wins Um, and then I guess here So this is really going to give something like, uh Say that it makes an item So what we're going to do is we're going to match on this And that is either going to give us an election result winner Which is going to be something weird like a reference to Uh, a reference to an item ID or We're going to get uh an election result tie Which is going to give us item IDs and then we're going to have to figure out how to break the tie And see if it's any happier about this What are all these things at the top? It's got a lot of stuff that's unhappy with us about Names of parent modules are not accessible without explicit support. It seems like something that's going to be unhappy about later Oh well Uh I I suspect what's happening is uh We're not like this This procedural macro depends on some stuff that's inside the schema module that we generated above Um, it seems that diesel used to return an iterator result. We got changed into Returning a veck for reasons 132 on github Really? Give me the github issues You said 132 That's a little sad. I don't know what uh, I don't know what to say about this It's fine. I mean in this particular application. We don't really care all that much because Like performance is just not critical I could definitely see that being annoying though Uh If I could post URLs, I think you can I won't be able to open them because the chat is on a different machine than the one i'm coding on But I can see the URL. So what is it complaining about here? queryable It's not implemented for i32 But vote is queryable Why can't I load? Oh, it's because of the join Can I I guess I have to select out Just the vote fields Uh Fine So for vote, we're gonna have I guess user ID and item ID And we're gonna select out just and they have to be same order. I'm guessing two User ID item ID and ordinal. We're gonna load that as a vote Yep, uh 87. All right. So here is where we get into these weird Expected reference Sure I'll give you a reference Right. So this is where Uh, so what group by gives you back is it gives you an iterator where every item of the iterator is a tuple of the group and the iterator for the group So here This is what I meant by map the map we need This for every group by we're going to get the group identifier, which we don't care about as the user ID And like the And then we're going to replace that with ballot But we want to for ballot map out the vote to just be the item ID of the vote See what it thinks about that. No method map found for that Uh into iter no method map found for Hmm. Oh, I guess Into iter mismatch types Why does it expect a reference does run election take like a It takes a reference to the iterator I don't like this api I mean, I agree. It should all be iterators. It's really sad that it all has to be over references I guess it's so that it can give back the appropriate reference here But it seems unfortunate Uh Is not an iterator. What do you mean? This is totally an iterator So it's saying that Uh, oh the error message you get a weird too. I think it's complaining about the sub iter So the the thing that it gets back from this map Is an iterator, but it's saying that the things inside of it are not themselves iterators Even though that is clearly not true Reference to the sub iterator Oh, that's awful But I don't think we can do that Who knows how this is gonna work out Yeah, I didn't think so So, I mean, there's a stupid way to do this which is just to collect all the things Right, like we could just do Intuitor group by Intuitor Map ballot is a dot collect And then say that this is going to be a Vec of Vec Of item IDs Right I mean, we could do that and then run this on votes, I guess I think that's the intention It's pretty weird, but doable Also means we're doing this extra collection, but It might be fine No method iter found for Right, this has to be Intuitor Good night. Yeah, and it's getting late in our way. I believe it Um expected Vec found Oh I mean, this is definitely pretty silly. There's a lot of extra collection here Basically, we're just like collecting all the votes into the appropriate groupings and then we're passing a reference that to the run election I wish one election would take a better type. So we did not have to do this, but The extra collections here are sad uh Okay, so Expected result can give you an election error. But what do these mean? Oh balls. Let's see what these mean. Um Overflow is if there are too many votes for something. Okay, that seems relatively unlikely Empty vote collection is if there were no voters And voters no votes Is if you reached a round in which there were no more votes Okay, sure So I guess this is if we get okay in this then do this we get okay in this then do that So really this is going to return an option item Right Because there might not be a winner Uh RCR our election error So overflow Seems like something where we're just going to give up This shouldn't happen, but we're just going to Give nothing Uh off topping annoying question your interface looks really slick Which interface the editor or the browser? I did a stream actually on my like programming setup if you look back on Earlier youtube videos Ah, this is so bright Empty vote collection And Voters no votes Well, okay, this is stupid. So this is really just going to be Uh Dot okay question mark Which is really just saying Turn all errors into none and then question mark is going to Because question mark work for option is just going to return right and if there's a winner Then we're just going to return the The item with that winner. So I guess let's see if there's a Yeah, that's it's going to be not all tasks, but all items Not find item ID Get resolved item Who knows what that's going to do dot unwrap. Why not? Uh this if there's a tie I feel like if there's a tie I want the one that's been on the list the longest Here we go with we're just going to take the zero To do maybe pick the oldest one Because remember because this is not a real election, right? We we can bias this selection. We can go Oh, I really wanted to pick the Like the one I prefer to do if there's a tie among the users Like if they can't decide I get to break those, right? Uh, so what does let I guess I should actually look up what get result gives you Get result If you query result you I should not be optional. No Not found should not be possible because we got an election result and we have the foreign key So that shouldn't be possible But why is it Why can't I do that users dot find This is update business. I don't It's weird Why are these all based on inserts and updates? Why is it not just a read? It's 38. What? Oh 38 Uh, that's going to be right. So winner is going to be an option item. That's fine And what else is it complaining about here? 96 Oh Item ID zero is that maybe what it was complaining about the type was wrong Uh expected i32 Find This is a particular type How do I cast from a DSL type as i32? Sure Uh Or maybe it already is item I can't use that as a iid iids How about that? Hey, uh the top left of Something. Oh, yeah, you're right. I should just do that Does it all yeah, I think I should also do it here And this Good call I normally like the light team theme later, but it's late at night and the editor is very dark All right local host 8 000. What are we gonna get? Uh, let's do Curl that address Whoa Failure No such column Items dot done. So it's saying That online 79 here All votes no such column item done. Oh, I probably just didn't Uh We changed this but I didn't realize the schema. Let's try that Great It aired with something because it failed to render the template That's fine. It's probably because this template is does not have what it should have. Uh, this is gonna be the old no, it's gonna be Rust live stream voting load for the next Rust live coding stream topic Author is me We're gonna do this for all of you um All this is probably gonna go away Just ignore that for now Um of this though There's a bunch of fancy stuff here that I don't want right now Instead what I want is just the stuff that's down there I want here. Yes, we can keep this one. That's fine and then Here we're gonna do four item and items We did call it items, right Items and winner for item and items if item done Then we're gonna just I guess hey, I know it'll be better title Now I just want to see that the data is there. I'm not doing any styling at all I didn't know body. We probably want the body to like have markdown or something It's initially. Uh, that's the one out. Great. Okay. So now it's currently empty Um, I guess we CD into Voters again And now we're gonna do this and we're gonna do something like insert into items Uh title body Values I guess I need to find my own Olds Where's the last time I did a poll? I think it's a while ago Just this And search for poll Really? Come on twitter. Usually it notifies you when there's a poll, but apparently not Uh, this one maybe Is there a poll here somewhere? No This is for the Rust open source contribution stream So the question is Is there an earlier twitter thread No, maybe it just doesn't go far enough back for where I had these I don't know how much stuff I've done since Um Finding polls is hard. Here we go. This is some stuff. So that's the open source contribution stream Where is the older poll? I just want to populate it with some like somewhat reasonable data Um, how far back is this? You get to see a view of my twitter stream. What's that? Here on earth is the last poll I think it should not be this long ago And we could uh, we can do an informal poll right now for people to You could try to just remember what these things were Maybe that's easier Although I should be so close now Fine. Fine. Fine. Fine. We'll do it. Ah, well, how about that? Uh Oh, that's a while ago. All right, fine. So we're going to do something like title Uh I guess async ssh part two It's going to be something like finish our implementation of async ssh so that you can write to sdn So that's one Uh, what's another? Uh, I guess There is, uh Uh, tokyo zookeeper testing flesh out tests Uh, and the It's tokyo zookeeper Completion flesh out tests and massage Up the tokyo zookeeper Implementation and api Um, I guess the one I'm doing this saturday might as well be listed So we'll do, uh, tokyo Uh, extra no, I guess futures extravaganza No, there we go. Um Full overview of futures tokyo async await and all the other Uh async stuff You've always wandered Great. We have some things now. What happens if I call this great? Okay. So we have basic database interaction That's awesome. We're like basically done, right? Uh, it clearly does the right thing Uh, I guess the other thing we want is something like if a winner This also means it actually did run the election Which is interesting I mean, there are currently no votes, but What happens if I do this? Terra template Uh, it's gonna be terrible, isn't it? Uh, where's the rocket documentation for terra Actually, maybe it's just dogs rs terra great Yeah, so context is the thing that we want That's fine But in rendering uh-huh see the site get started data structures Variables, that's fine dot notation still all fine How do I access something that's inside of an option? Maybe I can't even Actually, maybe maybe I just use it as a As a loop because you can iterate over an option It's a little bit stupid, but that that might be actually the way we do it fine. So we're gonna do Four winner in winner, which if it's none it's gonna iterate no times and if it is some it will iterate once Then we're gonna echo out Something like current winner title, I guess great Curl that okay, so initially there's no winner and then I guess we're gonna do something like insert into users username values bob Because bob is always the one voting insert into votes user id item id ordinal And we're gonna insert I guess one one one So bob votes for async ssh part two Now there should be a current winner There is not though Why is there not a current winner? I guess we're gonna have to do some debugging Show me all the votes That seems handy Oh Oh, you it That's why it doesn't pick up the new It it actually parses the templates on compile. So that's why So we need to restart the server. All right. So now internal server Try to iterate on container winner. That is unsupported. Okay, so that my little trick did not work Options are apparently not iterable Yeah, you're right. Um and for instead of end if but Oh, hey brine um But how can I use tarot to display an option? Someone must have asked about this Option there we go That's also pretty unhelpful Okay, so this doesn't It you can't actually get to the thing that's inside Is really what you're telling me That's pretty annoying Uh, I guess we can I don't know how to Well, okay, the stupid way to do this That's awful. Why did they make me do this? Uh, and it's gonna be a vec and we're gonna do run election Into iter dot collect Really the argument here is that Tara should Tara should Allow you to write a four over anything that is into iterator as opposed to defining its own collections But I guess it doesn't do that then option would just have worked because that implements into iterator Still doesn't show a winner though Because apparently there are no votes. That's what it's claiming. So why is it claiming that? If I do say Give me all votes Dot load Vote So this is like the most straightforward give me all Then I assume I get what I want Like I assume I get the vote there Okay, so that does give me the vote and then you're really just telling me that This thing Is somehow losing Oh, that's probably because I my guess for id is wrong All for my this No, no, it really is one And Bob really is one So the join should be fine And Done this falls for all of them. Well, I guess Let's We do need to select So let's see what that gives us So this is with the join but without the filter That still gives us the vote And with the order With the order still waits if this filter is wrong Oh This is filter all the things were done as false Whereas I want the opposite Why Do they also have where They just chose him to invert the meaning from sequel No like If I if I filtered by true is that gonna give me all the votes So strange No, that so just the filter is broken Somehow I just do this like will that give will diesel print my query if I do this from Join okay, so it joins On Item id is equal to id. Okay, that's fine where clause We're done is True Okay, so filter so it really should be false Right, that is the correct expression Good morning. Wow. You're in a very different time zone than we are So it's impressive So I guess the question is why is this filter? Filtering out the one vote that we have Because apart from that, this looks entirely right. It's an intertwining. We're done is false and that gives no rows Can I make diesel print the sequel query? I wonder Huh, uh diesel debug query. Thanks So I should be able to do something like diesel debug query And then give it just this I guess I mean, that'd be awesome if that works No expected reference I can give you a reference No, that's not what I wanted. All right, that seems good select Okay from votes join items Why does it put the join inside? These brackets, I don't think sequel light is going to let you do that actually So specifically, I think this Where this is false No, that gives you a row So why on earth? Does this load vote Con Why does this then give me no votes? When executing the same thing in sqlite does give me results Unless like the representation for false the diesel uses is wrong that Uh Is this stream about what? Well, this so this stream is a relatively informal one where I'm just writing a Simple voting site. Oh, it's snowing outside Um So it's not really about anything in particular apart from building this thing We're doing a stream on on saturday though, which is going to be about uh, tokyo, which I think is going to be interesting Why on earth does this give me no results? What's the difference between load and get results? Maybe that's the place to start load uh-huh And get results alias for load fine Get results. I like that better than load anyway Okay, well What if I do this Maybe it's just the way that What I feel like diesel is just like giving the wrong query It's like encoding Like false incorrectly or something that's so weird Because if I run the same query as diesel is telling me that it's running With false there. It does the right thing. Why why why? And done up here as a bool I feel like I feel like this is just broken. This is wrong Uh, probably won't help but debug query is generic over a back end Give it diesel sqlite sqlite. Just make sure you're printing this. Oh Interesting Um, that's a good point So you're saying debug query Oh, I see what you mean. Yeah. Yeah diesel or something like that Sure. No, apparently not What did you say it has to be given? diesel sqlite sqlite Yeah, I mean that that looks basically the same Right So if I run this and then for the prepared statement parameter, I give it f for false Then I get the right thing Your false Is sqlite not typing these correctly? Oh, I bet you So this string representation here is actually what uh Is used by other databases, but perhaps sqlite is just not strict about it Okay, so maybe this is our fault default false And then we're going to do we're going to recreate the schema And then we're going to reinsert the things that we had so like this and this and this Where's the user And now false gives one Okay, well, how about now Okay, great. Now we do get a vote Okay. Yeah, and it identifies the current winner. Okay, that's stupid, but yeah Uh, we're building. Okay. So the basic idea is to build a voting mechanism for voting streams voting for new ideas for streams using for those who have joined later using rank choice voting where can where voters can basically choose Multiple candidates and the order in which they prefer them And then the election takes all people's preferences into account and this lets me Let's people vote on multiple streams at the same time and then that will be taken into account going forward Okay, well this seems to work. Okay, so we it does give us a current winner now So we're like It's going along. It's going along. Okay, so that now all works Uh, I guess the thing we would now try is something like We insert Alice And Alice as user id two is going to vote for Two and bob Is going to vote for two in second place Right. So what this looks like what we've basically set up here is um, let's go to this again Uh, that's not Oh what I wanted. I wanted you to fill with the background color Um, so what we now have is basically Uh, so we have bob's votes and we have alice's votes Right and wow That's a terrible square or rectangle. So bob has currently voted for story one and for story two Alice has just voted for story two and nothing else right As in theory the it's gonna should start out by looking at the first preference of each user It's going to recognize that there's a tie. It's going to eliminate Oh, maybe it eliminates both candidates I don't actually know what it does in this case In theory it should eliminate just this right and then place two and then realize two will work I don't know what it's going to do in this case. It might just declare a tie I guess we're about to find out so in theory there's like something sort of like a tie here It now says zookeeper completion Okay, so it is going to a number two and then let's say that eve is here too And eve votes. What does eve vote for eve? votes for one In first position. So now There are two votes for one in first position one vote for two in first position and one vote for two in second position Which I think should mean that option one wins Great. Okay. So the election stuff seems to now work out. The question now is If we now update items to set done is true where ID is one So now item one is no longer an option Then now it should fall to the second one. Great. Okay. So this is basically what we want, right? Now the same votes are still present Um, and we didn't have like everyone didn't have to vote again, but you still maintain the preferences that are in the system Fantastic. Okay. This seems pretty good. This seems like we're getting close to what we want Uh, but of course currently users can't vote except through this stupid mechanism So we're gonna have to have some kind of interface that they can actually use So that gets us to this, um We're going to show winner I guess Uh, do this though. The question is do we even show the candidates here? I think we just show the winner Uh, and then what we're gonna do is something along the lines of I guess I should find out how these how we extend these for multiple pages Uh, show me the docs for doTERRA The introduction Uh-huh, uh-huh, uh-huh. Don't care about any of that. That's not what I want I want Want inheritance Great probably Only care about that part. Okay, so we declare a block Block uh And then my guess is there's going to be something like Also, remember, this is still stupid, right? This runs the election on every page rendering Which is probably know we want what we want long term Uh So we're gonna move Static index to be static. Uh, I guess Base dot html dot tera, and then we're gonna That's that was kind of stupid of me Oh, uh, and then we're gonna edit and now we're gonna have an index Html tera and my guess is that there's something like extends. Yeah So that extends base, uh, and for the block content Uh index is going to do All of the stuff we did before I mean it won't actually but for now we're just gonna have it do that It's also going to do What was the other thing we did for winner and winner? I guess this is going to be end block Uh Here it's going to do P strong again, we're going to fix up all the syntax and stuff later for the styling Uh Current winner is winner the title Let's see what that thinks Great, so that just seemed to sort of work. Oh apparently not Uh, does this have to say static slash Or something Huh So there's something I have to do here To set where it's going to render Right, so this says render index Uh, is this in like rocket tom or something? Template or static This should render index And index tries to extend base Oh, why does it just say base dot html instead of base dot html dot terra? Oh, maybe it's just base Maybe Apparently Great Okay, so now we have that Uh Oh, I see you can either give the full path Or I guess you can just remit the extensions. Uh, how are you linking terra for templating? Uh Oh, I'm just using whatever rocket gives me so rocket has this feature called terra templates in rocket contraband that just Does the right thing again with all of this I'm not really trying to implement this in sort of the best way I'm trying to implement this in the most straightforward way I can Because I this is not going to be a large site. It's not going to be sort of a production site It's just I want it there for voting Um Yeah, it's like very straightforward Um, okay, so now we have an index page and I guess Really what we want here is something along the lines of a we want like a form and I guess we can do here whatever Uh, what do they do for the form? I samples to do static index So they have a form of some kind Here And we're gonna have a form On the front page And that form I guess we can do like this or something or actually we can do even better Oh, it did not like that Why does this not Oh file set file type What I really want here is like a slash I get I guess login I mean it it isn't really a login right, but I don't want any of this fancy styling stuff. I really just wanted to have a single thing that is a placeholder And we're a unique The name is going to be username. I guess the value Care autofocus. Yes, indeed Seems great There are going to be no messages in this form Forms are so great when you don't have to do any kind of validation on them Uh submit and the value is going to be Let me vote And then we're what we're going to do here is something along the lines of having a vote dot hml Tara page and on that page We're going to show all of the options So that's no longer going to have that it is going to show the current winner It's going to show all of the items Whereas the index page is not going to show all the items This posts to log in so I guess Uh the main we're now going to have to Have something along the lines of posts to log in Right, so this is going to post the login and It is going to have a Oh, what's it to do form? I guess here they have something in source main. Maybe Where is this form type? Oh, that's the the from form business that they had so they have from form for that And we have a form too It's not a very fancy one, but we have a form too. We have a I guess then a new user form Because we have a new user Right, so this is going to be a new user form that maybe So it's going to be a form new user It's going to give a redirect Uh, I guess user is f dot into inner if User name is empty. We're just going to set it to be required and we're It's going to ignore the user if they try to do something stupid So here, I guess we'll be required If it's empty, then we're just going to render the same page again I guess it's just going to be this That's gonna It's going to come back to bite us No, no, that's We're going to be it's going to be even stupider. It's going to be redirect to slash in fact I guess we're just setting uh Right, right. I think we're just going to do It's really just going to be if user Add It's not even going to be an is It's going to be uh let you Is user I almost want something like insure, but it's really user Login And that's really just going to be user And then I guess this is going to have to set some kind of session Right that we're going to rely on later and then we're going to redirect to slash again Um And then we're going to render a different slash depending on whether you're logged in or not. Uh, okay So user login, huh? So info user And a pub offend login It's gonna take a connection. It's going to give you back a user. I suppose Uh, this is going to take a user name This is going to use a name, which is a string And it's going to make you a user and so that's going to be similar to what they did for Like task create Uh, whereas I guess For us it's like a find or insert I think we want this Users and this is going to be Insertable and then user is not going to be insertable And now this is going to give me just the the new user object So this will be a new user So maybe this is just a new user And this is make this is going to be user dot login itself And con and gives you a user and then we're going to do something along the lines of We sort of want to do a look up how we're going to do this Oh, that's the other thing I've forgotten to make right? Oh, no, we have a unique index on your name. Okay, so really what we're going to do here is Insert into it's going to be so stupid, but um self schema users table And we're going to insert in Self execute Right, so this is where it gets stupid. Uh, this insert into is going to either fail or succeed And Actually, we don't we're going to not even care whether it succeeds or fails Uh And sure that the user exists and then we're just going to select it out So These will have a good just like Just want to do a quick and dirty. I guess I can do a find Does it have a straightforward way to do that? Right? Don't have to think See select. I guess it would just be Select users table And then I would do something along the line set dot find Uh self username Maybe and get results. This will be a user Unwrap Maybe Apparently not unknown. Oh, this is probably um It probably does not turn, uh, like, uh camel case into snake case for you Ooh Oh, it needs to be called the same new user I wonder if I can just make that f Uh Selectable expression I mean, maybe I can just do this instead Users As all users It seems annoying to have to do that all the time, but I guess I guess I I am also not putting in the effort to learn diesel So it's there are probably easier ways to do most of these things expression is not Oh, right. This has to do Something like Uh, what do I have to do ID as pk And this is going to be right the filter here is really or the find is really a Uh Or user ID. Oh, sorry. This is not an ID is not what we want. We want username And then here We're going to do Username.eek That's really what we're trying to find I expected dual found integer. Oh find is by primary key. I see So it really is filter. I guess this is going to be as users Otherwise you have an import and a and a field that have the same name Which is probably going to complain about All right, let's see what that gives us So we now have this awesome page Like low and behold This page The current winner I'm going to put in john. No, I'm going to put in alice Let me vote who Uh Did not like that No matching roots for post slash login Really Is that so So I guess what that means is it's really It's um Claiming that what I'm giving it is not one of these forms Because remember how all of these um, oh Why does it say new? Login I think It might not matter, but I don't think the name of the root matters, but I didn't think so I think what that means is uh, remember how Uh rocket takes the the arguments to the function is basically like a A filter of what does this particular request require in order to be executed what we're saying is requires a uh A new user form And so the real question is how does it know whether we're providing that? Uh, and if we look at index How would it know so name username is apparently not sufficient What does um What does this do that's different? So this also does from form. It's just called description And in main when they depend on it Uh, I don't seem to really do anything different So it's got to be in the template somehow Name description There's nothing else there really So why why oh why? Is this not being satisfied? Huh At least in theory, I think this should match The form that we're posting The post slash login Hmm Is there a way to get rocket to be more verbose with logging? I wonder Oh a rocket Routing that's an outfit Uh, that's forwarding increase request Well, so this is stuff we're gonna need for sessions, but Here body data Oh, okay, so those names just have to we can just call this input and then this can be called input That's easier um Right, so there has to be some t that implements from data and We know that new user implements from form So the question is why is it not right? So here there's like a derive from form And then it can take form of that type, which is the same thing we have Uh, the data that arrives isn't of the correct content type The request is forwarded The data doesn't parse You get something else But we get a 404 Forward or failure can be caught by using the option type. I mean, I guess Let's see what option gives us first Just to see whether it now at least gets called Far too many tabs open now. Yeah, it doesn't even seem to get called Oh, is it because we don't even mount it? Yeah, that's why we want Index and login to be mounted at slash And we don't want this to be an option anymore. We don't want this to be unwrapped. We just want it to do the right thing and now refresh beautiful It didn't do the right thing, but it tried uh Oh, no, it did the right thing. Okay, so it's because we don't set the session. So now Presumably, what did I give us the username here? Okay, so if I need to give john now and first let me vote And if I now check the database and do select all from users There's a john. Okay, great. So now it does it creates the user if they don't exist And if they do exist, they don't create it again, which is exactly what we want Now we just want it to set the session for the appropriate user Uh, which we're going to do very straightforwardly by Um, what's the good question? How does rocket set sessions? Okay, so this basically doesn't have any login. So let's find an example that has little sessions session great Hello main They have fancy login cookies cookies So we're going to also depend on rocket cookies And we're going to do cookie. So this so see here how this is now saying that Login depends on this additional resource now. Namely it needs to have access to cookies and for us what we're going to do is Uh, in this case cookies. I don't know if it's going to be ad private. It might just be ad We don't care that it's private. Um So we basically we don't care if the user gets to see the contents of this cookie Basically, there's going to be plain text as opposed to uh, As opposed to being encrypted in some fashion So instead, uh, we're just going to store user id and u dot Great Now what do they use here? User right so so here you can see the the way in which these requests end up being used in rocket So notice that all of these are forget slash login One of them is sort of preferred and the other is rank two and well the rank one has a requirement that you are a particular user Right whereas this one does not have that requirement And so this one if you had a user so I guess this declares a Where does the user come from right? So here this is how it uh checks that there is a user In some sense, I don't really want uh, I wish there was a nicer way to do that I mean, I guess this is the nice way to do it. I wish there was a fast way to do it But fine, uh, we're gonna have a user all the user really is is the night 32 And It's just gonna parse out it's gonna get user id And I guess So this is a little bit stupid because you could totally imagine that there's some user out there There's just gonna like enumerate all user IDs and make all the votes It's not going to be secure anyway. It's fine. Uh, so user id it's just going to create a user for that user id So this is a way of saying given a request. Is there or is there not a user there? Right And so once we have this we can now declare this This prefix or this additional request Modifier, so we're now going to say that this is rank is two this sort of index with no user associated with it It's going to be the fallback and here if you have a user Then we're going to in render vote Right Uh, arguably the context might actually need to know whether you're logged in or not to know whether to show the options In fact, what we could even do is say that um We could only load basically we could only run uh, or load items if Uh, if the user is not logged in, but let's just ignore all of that for now Isn't that great So This is gonna be vote Uh votes I guess Because we're also gonna have to have a vote endpoint for submitting the votes Uh, all right, so In this case you're gonna be able to vote Once you're logged in that is Oh, did I miss something is rank like different somehow? Oh, it's inside See rocket really likes using nicely for all the days Uh, I guess I need requests them from requests and some things these things Give me give me give me. I probably have a duplicate import now somewhere Also use And form is double imported That's fine, but user I can't use because there's already a user type. So this is gonna be off Good luck. Oh, have a nice day. Thank you I mean, I did tell you this was uh, mostly gonna be me hacking on a Very straightforward website. All right. So now I think in theory we should be able to go here and go john Hey, and it shows me the items perfect Uh, and now I guess there's no way for me to log out Uh, so we'll bring up this and storage And then I'm logged out again great I guess I also sort of want the ability for this, uh Log in to be long term. I don't know if there's a Basically, I don't know what happens if I close my session and start it again Uh John Expires on session. I'm clear. What's the expiry date on this expires session Yeah, it's probably fine Doesn't seem terribly important Again, this site is not intended to be secure um Okay, so we're getting pretty close now I mean, there's a lot of styling that has happened But now we have this list and now the user needs to be able to move that list around in order to change their votes We're getting pretty close to that Right, so for vote altera, we're now going to use this, uh, sortable business Just get rid of some of these because they're not terribly, I guess that we can probably keep Don't need any of these So now for the sortable business I think if I remember correctly, there's like a cdn part here for how you load it without having to do anything Wait seems perfect cdn Great that that's what I want Uh, here specifically I want This so now we have sortable And then how do I make one? Oh Sure I'll bring in bootstrap That seems fine You know given that we are not terribly Don't find it terribly important that everything Like this is very straightforward, right? All we want here is something like this It seems fine. I don't think this idea is important I guess valid And then you're saying these should use the class list group item Do we think all this is going to magically look great now? And then we'll do this and It's going to be document target element by id No options We don't need options where we're going Now if I go here Hey, I can drag and drop them fantastic Beautiful is what it is And then we're going to have to make it save Which is probably going to be harder. Also keep in mind. Uh, we're going to need this, uh, if you remember the ability to in in, um Uh In this kind of voting you Are able to not vote for certain things too. You don't have to in ranked choice You don't have to rank all the choices And so we're going to need to have some kind of barrier that you can move around and say everything below this I don't care about. Uh, so we're going to add this, uh This sort of uh this group item, I guess, uh, which is going to be Uh Canceler Don't have a better name for it yet Uh, and what we're going to say is that It's abusing things a little bit, but we're going to say that a canceler Anything that so a canceler and anything that follows a canceler Any list item that follows a canceler, uh is going to be Background gray or something right Right, so the canceler if I move it to here that becomes gray And if I move it down, it's longer gray And so this has this gives me a mechanism for saying anything below this. I don't care about again The styling is terrible. We'll deal with that Uh, and now really the last thing we want is the ability to say To have this list be saved right so currently it's not saved at all Um, it turns out the sort of bowl has this neat feature called store um here Uh where you can say Hey, uh, you can say whenever you want to render the thing Oh, I don't think I need do I need to implement get I don't think so So specifically this is like whenever the order changes this function gets called So currently we're just going to set it to basically do nothing interesting Give me back my console Uh, do I actually need to implement it? That's kind of awkward Uh, I don't think I need to implement it. Maybe I don't need store Because I don't I'm not going to dynamically load anything. So maybe there's just like an on On update sweet. Let's do that instead On update and want to give me Same as on end. Okay, so that gives me an event and To target list. Sure Always want the target list. There's only one list So let's see what that gives us. So now drag this do Currently not Oh, that gives me that whereas what I really want is I want the the whole sort of bowl Is there no way for me to get that? in these Oh, maybe Maybe this is even simpler. What are sort? Sortable Is this Can I now just use sortable? Maybe Because we're about to find out Great I don't know what these ids are Oh, does this need some kind of like I guess data id or something? That's going to be item id Is that going to make it happy? Yeah, great. So now they're no longer auto-generated And then this I guess has to have something like data id is What does it say if you the what's the word for if you're choosing to not put something on a ballot you are I guess boy, I don't think it's important. So we're gonna say We would be so order is going to give us the full order, right? So in this case, this is uh, two is the top one then void then three Why is one? Oh one has been completed. That's why So what we want to do here is We want to get a list that is only the things that have not been voided. So in this case, we just want two Uh, and I think That's a good question What is why is I guess so we can say uh Var votes is an empty list and for oh in order We're gonna uh, if Oh is equal to void I'm choose the rust code now Then break Otherwise votes dot push Append and now give me loads What does this look like Oh missing It's not rust code Oh, so it is push Zero one two, that's not what I expected For oh in order. Oh, does this just give is javascript being stupid? This gives me the indices doesn't it? So Okay, so now it just gives me two so now it's given me the prefix that is before sort of the voider And that is what I want to store like this is the set of uh of votes that I actually want to store And so now I need to send that to the server somehow And we're going to send that to server in the most sophisticated way possible using Even though fetch also lets you send stuff A little bit of a weird name So there uh, there's a using fetch. That's what I want Uh, huh, and what I really want is a fetch Right, what I'm going to do is I'm going to fetch Uh, I guess this is going to be Slash vote With a post Uh Don't care about the mode. Don't care about the cache. Don't care about the credentials Uh, it is going to be application json This is not rust. Well, I think that's true But when you're writing like a web server when you're writing a website You also sometimes need to write stuff. That's not rust sadly I I promise I do have rust code here. It's just we're mostly done. Well, we're going to come back to it a little bit Um There should be no redirects. I don't care what I refer and the body is just going to be votes And I guess actually what I want this to be is uh What's the way to turn strings into integers and just int They might just be And don't care about that Just want to do that Great, uh, let's see what happens. So if I go here now I reorder this int is not defined Oh JavaScript convert string to integer It's just int a number Because of course it's a number All right, like so array two did that send a network request post a vote with the contents So it included the cookie I assume Uh cookie. Yep user ID is four And included just the two perfect. So sent an array and that makes us happy So now the only thing we really have left to do here is um There's going to be a post To slash vote Uh It's going to Vote I guess we're going to make sure that vote gets included here. So we don't run into the same trouble as we had before Uh vote is going to require that you have a user Uh, which is off and a con which is that And it's going to give you back. I guess a template although it basically tells you nothing And what that's going to do is just Uh user Vote I guess it also gives you a form sort of How are you supposed to get jason data? I wonder, huh? I guess Uh, it's almost like we want to deserialize Yeah, I think what we're going to want to do here is actually say that this is A vote So this is like an object now Um, and then in schema, we're going to have another sort of from form Actually, this is not going to be from form. It's just going to be a deserialize it's going to be Ballot And that's just going to have votes. It's just going to be a vex of i32s And then the question is is there a way for me to To put this just here, I wonder Maybe the Rocket thing has that If I just want to parse jason, aha Drive serialize perfect data is task and it's jason fantastic All right, so Probably wherever this is from It's also a jason And we're just going to say here. What was it data is input? I guess ballot This also takes a ballot which is a jason of ballot And then we're going to say user dot vote And we're going to give the ballot dot engineer and then I guess we're going to Can this be string? I feel like that can probably just be string voted And now what we need of course is Oh, that's awkward I think it has to be user colon colon vote and then it's going to be user dot zero, which is the uid And then in here on user I guess it could be on vote to vote save ballot And what save ballot is going to do I guess it also needs the con So Is it's going to take a user id It's going to take a ballot It's going to take that connection. It's just going to clear all of the user's current votes And then it's going to add all the new ones What are the main crates you're using so this is using rocket for sort of the web stuff It's using diesel for the database stuff and then it's using the rcir create for The rank choice voting And I guess terra for templates which sort of ships with the rest Okay, so save ballot is going to be really stupid It's going to do all votes Uh filter Where user id equals uid How do I delete? Is there like a diesel Delete great Not execute con Unwrap maybe not unwrap is okay sure Ah unwrap So we're deleting all the user's old votes and then we're going to do uh Is there a nice way for me to do like insert many like maybe under diesel insert into For this It just needs I see so insertable is Probably Okay, so it is just single insert that seems fine Uh, so what we're going to do is for uh, like ordinal I guess I and I id so this is the the ordinal number and the item id in ballot dot votes That is all there is in ballot, right? Then diesel Insert into and I guess here We're going to insert into self schema votes table Values and then this is going to be Uh, what are we inserting? We're inserting I sort of want this to really not be that to be Can I make this be vote is uid item id is id and ordinal I don't know if it's going to be happy about that probably not Uh expected item On 91 here on 91 sure Uh, we don't have delete. That's not a thing that we do. We don't delete things But it's because this has to be into iter dot enumerate So we need enumerate so that we can get the ordinal number Right because remember we need to store the order of the votes And this is id 32. That's true. Oh jason in request Then where is jason? Oh from rocket contribe Sure, I guess it's not considered sort of core to rocket. I guess that makes sense Now what? Am I blind rocket contribe jason jason jason jason Oh, is there like a feature? Oh, it's It's because we said default features none We really mean we also want jason Or how many of these oh cuz terra is not on by default I see Why does it why it's been set default just don't do that I won't serve also by default Don't disable the default. That's silly right so Select all from looks Right, let's see Uh, so who am I currently logged in as that's a good question I'm logged in as four So what we want is here, uh Where user id is for So user id 4 so that's john has made no vote so far And then we do this Oh did not like that at all Right it's ending. Oh, why does that empty? That should not have sent Also, we don't need the static css directory That's not necessary neither is images Um That is a little bit disturbing though. Why is it not Storing that what do we get in our console? We get an empty array So why is the request that's being sent out content length two Should be an empty Why is it not sending the votes key is what I'm wondering Right like why This is what I I wanted to give like votes Nothing that's really what this should return But it's apparently not what it does return So if I do this What now it works Okay, well, so now there should still be no votes for user four if I so this is uh Two and this is three so if I move this to here Now this sends That I have now voted for two So if I now do this There's a vote for two in ordinal position zero if I do this Should now be votes for two and three What's for two and three with two coming first if I reorder these two Should now send three and two Which means that here it's now three and two okay great So now we have like the whole setup in theory now. We could do a bunch of votes. It's if we now refresh Oh, I guess this should maintain my order shouldn't it That's awkward It doesn't need to retain my current ballot Um, I guess we can do this with a left join Um, so the idea here is that if you go back to look at your ballot, you should see your own ballot um Which we can do by For user This is going to be not just all Um, so if we go to schema here if we're given a user Uh, then what we really want to do This is uiis is going to be user dot zero Uh for user then we just we don't want to load all of them. We want to left join Oh Yeah, no we want to We want to left join with votes Which is a little weird But doable I guess we need to declare this is joinable Already is joinable We're about to find out so we're going to do a left join with uh What's the join key thing in schema? Votes table so we're going to left join with that And we're going to order By Uh, I guess Ordinal Draw ascending So the idea would be that the nulls are ordered after so therefore you first get your own and then you get the others this I guess we need to select out It's true. I do sort of just want to select out item, but I don't know that that's gonna work Yeah, exactly This has to select out the things of item that we care about which is really quite weird Um I wonder if there's a convenient way to just sort of select all the fields of a given thing So for here The dsl we end up with Here No query dsl So for this is there a convenient way for me to just like say all the things of a table Name oh, I see I think I can do something like schema Uh items like all It might not be all It's probably called something else Um particular the thing it generates methods No um so Probably generate some kind of like star Because it certainly generates one thing for every field I just don't want to name all the fields of items, right? Uh, actually, I guess the real way to do this is just look at the table This What does it generate? All columns Oh, so close So close Great Um, it does mean that we lose the information about whether or not the user is voted for something So I I wonder whether I can do like item comma option i32 maybe And then say I want that and also Uh ordinal Oh now the types are not going to match for context Also, it did not like that Why did it not like that? Uh, I expect it never found once All right, there was a point about this For left joins Hmm Oh dot nullable I guess that's what I knew and then I guess we also need this to return to same So this is going to be option i32 except No, we never need all we got rid of that right So context I think is really just going to be an option of items Because or it can just be Not used if not logged in. Uh, and now if we go back to Uh, if we go back to our index page, sorry our vote page Uh This Is now in theory at least going to sort by Um Sort by the the votes the user has already given in the past I guess did I not change this type? Which means that the order should be preserved and the only thing we need to make sure is we insert the Sort of didn't vote item in the right place now Oh This is now item dot zero dot title because one is the ordinal Really? That is a very good question. Why does this not give I guess we can just try to print item See where that gets us, but that doesn't really seem like it does much Right, so this still Huh Apparently it doesn't really like that sort of being given a tuple here um Can I print like item dot one? Is that a thing that I'm able to do? It doesn't seem to print those Hmm, I mean it could be that's necessary, which Shouldn't think so Huh, um, I guess we look at terra and looks at um Data structures math comparisons, what about tuples? Is it not I really don't talk about that built-in tests, maybe Is defined so I guess if uh Item dot one is defined And hello Although I wouldn't expect that to make a difference I mean, I guess we could uh Just sort of for own sanity's sake check that it actually has things in it Because we could totally have screwed that up, right Something ain't right here This is from user user That's so silly Let's try all of that again user See how that works out Well, that's certainly too many things How did that happen? There are not that many items Why are there this many? Oh, I bet you the the join is now wrong. It's like joining by uh Joining by user id or something maybe Very interesting. I so so the the other thing we want here, of course is uh Something like if item dot one is defined It's a little awkward that this has to work this way But I think we might actually have to duplicate it like We we want this void in between, right? Is Undefined so that should give them to a sort of in between That should put the separator in the right place Uh, I think it is not matching the root. Yeah, it's just Yeah, I guess you saw the fix, right? so now The void is still not happening in the right place. It sort of seems to think the user Voted for all of these so let's uh do like a A sanity check of what comes back from here Um, my guess is it's the join is doing something weird Yeah, see here like this is what the join gets back Just clearly wrong That's so stupid. It's I know we're not filtering by user Filter user id dot e UID that's So stupid so stupid So we were like just like looking at everyone's votes Great. So now if I reorder these And then refresh and it stays if I move this up refresh Does not show the things that are underneath Not what I wanted it to do But You know Something happened Not quite what I wanted to happen Let's keep that in for a sec longer Oh I guess is So what is it doing? It's not only getting one thing Clearly it should still be getting Oh, no, that's right. It shouldn't no it should be getting both. That's the whole point of the left join right that This should give us all items. Oh, no, it needs to be a part of the left So, okay This is now joining and then selecting where user id is equal to something But if the lift join if we don't have a match for anything the left join isn't going to match So user id is going to be null So this is like user id is equal to that or null Or we put it as a part of the left join conditional So I guess Where's our left join? I mean that doesn't see inner join. That's fine Um, can I add conditions to the join clause is what I want to know, right It's here Oh, right dot on I wonder if this is I'm going to get rid of the normal join condition. It probably is isn't it? Yeah, I think I'd rather I think it's clear to do this Uh Or What's the filter What is the or filter? Right So or filter so either the user id is this or Uh user id Eek Yes, where does eek come from is the other question Um, because we sort of want to we want to allow it to be null Uh, I guess is null Yeah, right. So either either we join Either we join either we join in those a vote and we filter on that user's vote or the user Uh, or the user didn't vote in which case we still want the item. I think I think that ends up being right Great So I put this here I refresh No Why if I move this up now I get nothing remove this here I do get that. I just don't get the other one That's so strange Okay, what if I Delete all the votes for that user then I still only get one Oh, so it's like now I get only the ones I didn't vote for Okay, fine. I guess we will have to do it this way then And it's going to be something like Uh I guess user id equals UID and And I don't know probably Uh and like Uh, I guess item id equals cell schema items ID I guess that's what it wants Compiled it's not quite what I was expecting Apparently that's right But I currently have no votes I haven't voted for anything. So this line should be up top And I am getting nuns Oh, I guess I might as well filter this on done anyway So this is what are we filtering on? done equal to balls right schema items So if I now request this both of these have none and so I would have thought that they would end up down here But apparently defined is true for none Is that the takeaway from this? What was the What was it this thread set about options and testing the option? Well, that clearly doesn't work because They end up above So if I here do like I print out item one My guess would be that it prints Apparently that's not a thing that I can do That didn't print anything out full at all Uh So so the the server is certainly saying that the ordinal number is none for both of these Which is because we haven't voted for it. So that seems fine But then why is item dot one defined? is I can negate it if that helps, but I don't feel like that should help Um, this does not work. I guess It just feels weird Because I think that means ordinal number zero would be Yeah, so if I now do this This ends up underneath because it's ordinal number zero The ordering is also wrong Notice the sums come after the nulls That's pretty open. So I so this means that In ascending ordering Nulls come first So I think what that means is we need to order by Something that is none descending first So something like user IP And then ordinal ascending to fix that problem So now at least that comes first the sum zero comes first um, the problem now is The sum zero is Falsy and so therefore this one It's awful And is defined does not work Right, that's because that's what I wanted to do, but Oh now it works Or or does not work Oh, there's already a knot there Okay Did did I actually vote for all of them? No, I did not vote for both It's false This is just returning true for both the sum and none I guess I could map it to a boolean Maybe That's awful. I don't want to have to do that. Well, so we're gonna have to do something stupid here like I guess the thing to do is like Into it or Map this is awful. This is Terrible And then map that into I and then or unwrap or false Is map true So we're mapping any value to true and None to false This seems like such a stupid workaround But now at least This will just be boolean Which might make it happier And this is now a boolean How about now? Great So now if I move this down refresh This up refresh of this up refresh Of this up refresh Right the things underneath are ordered basically randomly, which is fine Like we don't really care about how things are how things you didn't select or ordered. That's fine. We can deal with that Okay So now We have all of that in place and now all that's really left is styling And I guess we should fix all of these errors or warnings Uh, find type table. Maybe this has to go in here It's like not entirely outrageous I can't be all of it though It's complaining about Insertable and queryable I think it just wants us to take all of these And move them into here And then it would be happy And then we'll do use self schema user item vote Uh, what's your window manager? My window manager is xmonad Although I don't particularly care about my window manager. Uh, I just want something that's tiling and this happens to be a decent one Cannot find type table in the scope I don't think that's it at all I think what this really is Is uh, it's telling me That if I go back to that to do Like missing a use of some kind source task This probably No, I have that. What is it complaining about? Because presumably this compile is just fine I would assume The query ID is something with diesel Huh Okay, do you think that applies to this to insertable and queryable as well? I guess possibly Man, it seems to work. So I guess I'll just leave it that way Uh, 50, uh, it's a generator file. Yeah, it's some kind of stuff like that All right, what else is there that's sort of like relevant for us Uh, 18 that can go away A flash message can go away Uh, user can go away It's saying unused attribute on 39 and 46 I guess maybe it's only used for inserts or something The insertable you can use No, what what I mean is The I'm the that's not the error I'm getting right insertable I'm getting a similar kind of thing. Well, actually it's query. No here. This is the same names from parent modules are not accessible But maybe And you're saying this is like I need this And those are not in the prelude No, that's I get the same error So it's not that 36 apparently I don't use users No items Uh, okay Using explicitly did not get rid of the error though All right, so we're getting pretty close I guess the thing now is going to be making this look decent. So we're going to do something stupid with bootstrap Get started Uh, I think that's what I already have but it could be wrong Face Oh Four It's awfully fancy Look at that, huh? It's got why why does my browser not let me do the full copy? Okay Don't want any of the JavaScript Uh starter template. Sure I'll take a starter template. It seems fine This I probably want that too After all it seems fine for this to be uh for this to be To like work with mobile Something where I'm happy with that goes away that goes away Body And then I guess that's fine And then for index fine Sure Give me like the most Deeming no layout sure Me now I'm really just fiddling with layout. Uh, okay this indenting is Not what I want See in rust table and in I just want this to not What's the You can never remember Stop is to Shift that what's the last one soft No, great. It's not effect rust code So that's what I wanted and then now if I go to base I do this Okay, fine That's Totally wrong. What is it doing with this loop? It's not doing the right thing. That's for sure an index I guess we also set the file type this All right base Here, I guess we want div. What's the thing class is container. I don't think I need to recompile a little bit Oh, I guess storage Let's pretend that we are not currently logged in great Sure Whatever the defaults are is exactly what I want grid Don't really need grid for any of this which is also kind of interesting Because everything is a single column content I don't think I need to do anything with this Um, I have no code. I have no images. I have no tables. I have two figures forms Great, how do I do that? Because there's a login form right there It's very important that it looks nice this form Don't really want to label I guess I can have a label. It's necessary I want that to be Beautiful So we're away where I can get the button at the end of the form integrated button Into my input No, no, it's gonna knock a knock there. I want that but I want it with a submit button No, that's not what I want Does not look like it wants me to do that. That's fine. I guess We'll just do we'll just have it be that and then uh So since I don't even want to submit button, but I guess I can do it Let me but Look how glorious it looks alerts badge No Okay, so I guess what I want to show Uh Ignore the warnings. Yeah, that's inspired Um All right, so this page is really the the core piece is really this part sort of right And so I almost want like a big It's a jumbotron That's not bad. It could be a jumbotron Certainly has a cool name Uh card Card card is interesting I might be what we want for um Sure Sure, that seems fine. So this is going to be h1 current winner And this is going to be one of these our title is going to be winner title Card subtitle we're not going to have our body And there's not going to be anything How does that look? Sure, let's make it It's not set it's with Great I'll do that Why is there no spacing between things? Like there ought to be spacing between things Aha card header extreme Unless you vote Unless you vote Courage people to vote. Why is there no padding on things here? Like what's the content How do I make things not be Stuck together Because currently it's all kind of stuck together and I don't want that I guess I do want this form thing to be leot Can I make them More like that maybe I have an empty cold that looks weird Perfect much better Now how do I have spacing please? Why is there no spacing? Uh, we probably also want something to sort of show that you're currently logged in in the on the Actually Twitter bootstrap Margin between things That's more what I want. So that was the discussion from 2014 That's pretty unhelpful From 2012 really well I feel like this is probably not not really happening So unhelpful I feel like the right thing is not to just like add a bunch of spacing myself Maybe the solution is that I add rows, but Like Just like feels wrong. You know what I mean? I don't know if these rows even have No, it's definitely not right Is the argument that I just like shouldn't have that maybe Contents no I Don't think there's anything about this here because they seem to encourage just like adding rows directly, but Won't everything then just be sort of stuck to the top like what's the vertical alignment suppose I could just put everything in one row Seems like a little bit of abuse, but Center What? No So you're saying I can't have rows. Oh, am I like not terminating something here? No, this this all looks right So I'm really not supposed to do this It's like what What this is telling me Because these are now suddenly columns I guess I need to add a single div. That's like a column Okay, well that didn't help at all Didn't even center things vertically That was the whole point I'm so glad I'm not doing web development anymore But I mean I know how to override this manually. I just feel like I shouldn't have to do that, but Like there's all the the the trivial solution here is this right? Hey, it's exactly what I wanted Hey, awesome All right register me to vote This is a little trickier because here When you're logged in that's still going to be there. So that's fine and then This I don't have to figure out what to do with this. So it could be that these are really just rows But I feel like really they're lists so component there's probably a list list group there we go Right. So dot disabled Really what I want But I don't have disabled And I sort of want to say that everything that follows something that is disabled is disabled But that's probably gonna be annoying to do Oh I guess this is something like I do not want to vote for It doesn't really need to have a p, right? So that's already pretty decent um But it would be great if I had a Does this look like So dot disabled really just does It just changes the color See that's not really what I want Voided let's make this be And then say that what it really does is something like background like relatively right Yeah, that seems good And dot voided itself should have like fun Actually, that should probably have a more gray background. Awesome. And then Apart from that this looks pretty good now So they're a way for me to like really style the things that are in there Don't flush No, probably not probably not custom content. That's more like it Right. So there are these like titles, which is basically what I want So it doesn't even have to really be a ul right, so I guess this can just be a div instead And then these are I think I want them to be As because they're not really links and then to be this group item Don't really want action But I want maybe those I don't know. I don't know what action is supposed to represent here Okay, and This is going to be something. How does that even look? Okay, that seems Fine and this is I don't know what mb1 does but I guess maybe that's what I want Oh, I just changed it the padding. Okay, that seems fine So this goes here these are the same Oh, I see. I also sort of want these to be Not quite that wide I want like ballot Is that a thing I can do Yeah except call six Seems fine. What if I just do And then I also define another one that is empty it seems like a That seems pretty decent Seems pretty decent indeed So now you can do like this This I guess those Right these would now Is this Not styled by that real question Oh This has to be div as well. No, I guess it can be It could be like danger. I guess and then this is now This group item Why is this no longer applying? Am I missing something? This is a subsequent sibling of that now Oh, that's what I was missing So now you can do this you can do this you can pull there great And I guess if I do this I can't actually affect the vote because there aren't enough people voting Okay, I guess I'm sure they're all kind of ways in which we would make like to make this nicer But we will not instead I think I'm happy with it now It doesn't look amazing, but it looks fine And it does what it's supposed to do more importantly particular. Let's look at Bob who put in his first vote a while ago Bob is now also going to vote for that and that probably changes the election great Okay, that last bit was not particularly rusty, but it had to be done Is there anything at all here that is interesting I guess db ignore dbsq is there anything in static? I guess that is really templates So how about we move Move static to templates and then I guess we're not going to serve any static files. We don't have any of those So all cdn from here and I guess there are some like e-print lines in here That we don't need Uh, and what was the last thing? Oh, right. We don't need the static files anymore. Get add dot get reset We'll pull this It works So what we now have to do is just put it somewhere. So I'm gonna stick it up on the server I'm gonna tweet out the url to it. I'll add the possible streaming topics to it and then And then tweet out a url to it and you can vote for things I think that basically means that we have what we wanted. Um, I guess I should create our repo uh neuro bow Sure website for doing multi-round Uh choice voting simple website so that no one gets any ideas about how to do this Uh, oh, I guess fine start here This uh Not most of this but I do have that one of these Oh, yeah, I the the the intention here was very much to add As few dependencies as possible. Like I just want something that works. I also for javascript development these days I just want to use only things that are in the browser Ideally, I wouldn't even use bootstrap, but then I would have to write more css myself. So like But fetch is fantastic fetch is really easy to use and that makes me happy Um, okay, let's see. So this now, I guess there should be a readme. That would be awesome, but I haven't written one yet Uh, ideally there should be a file explaining how you run this Uh, I might write that up at some point. I guess the thing to do would be where can I put this easily? Uh here maybe sure Why not put it up straight away View light three db Light What? Oh, that's fine. This is just the drop table statements. Um And then I guess Actually, let's do something like Really, I don't have screen installed in this machine. Oh, I'm on the wrong machine Okay Run it in release mode Seems great. And then I guess we have to do something like Under forward This to I don't think this other one is running anymore. So I think this is fine. Uh, this is going to be slash Live coding sure live coding. Well, that's not a great sign. Oh, it's just doing stuff. Uh Arguably, I there's no reason for me to build this as release, but it seems fine Uh, I guess I should figure out what I'm going to put in there So the lead from users The lead from items From I guess I need to actually think through what streams we might do now. Um This might be an interesting thought exercise. So title and body Let's see. So there's definitely Uh Async ssh part two could have just reused what I wrote earlier here Um, I guess another would be Uh polish tokyo Zookeeper, so that's definitely one Uh Futures to start against that we're already doing that's the one we're doing on saturday What other things have we had? I guess, uh Open source contribution stream Take two another Do another rust open source contribution stream where we uh explore and contribute to Suggested open source rust projects What else have I thought of doing? Trying to like backtrack through my head now. Oh, uh port Uh Flame graph This is the one I really want to do myself, but We'll see if anyone else want to do it port, uh Brendan Greg Brendan Greg What else do we have that could be interesting Um Really need to sort of dig back here of other things I wanted to do I guess we could just look at stuff we have from the past, huh? Like things we've built in past streams Well, this is from the open source contribution stream tokyo pool is kind of cool, but not really suited for A stream Oh, there's like finishing making tsunami asynchronous, but that probably requires that we finish async ssh first But tsunami is certainly a good candidate for something that we will want to do more stuff with because if any of you have suggestions for streams that either you've heard me discuss in the past or You would like to see now would be a good time Yeah, I can't think of anything sort of off the top of my head that I've also wanted to do beyond these So I guess let's leave it at those for now Uh And before any of you get any ideas, uh, she doesn't matter This is so insecure, but it's fine. Uh Even true it is uh No I guess we're still No stuff stuff too. So I guess I'll pin it to today's nightly And in theory we'll be able to vote on things The one thing I'm worried about this. It's not so much that people like vote as other people because I don't think that matters Uh, but you might accidentally use the same username as someone else and If you do that, you're really just modifying their vote as opposed to submitting your own So it's like some argument for we should have that not be the case Um, like four out of 166. Yeah, this server is not the most powerful one out there I guess we could write or read me for this while we wait uses ranked choice Voting There's a website for it. That does not seem like what I want I sort of want something that explains what it is not where it is Sure, that seems fine. All right, uh This is ranked choice voting to allow users to vote on Uh, I'm going to the next rust live coding stream. Why is this htdp? That's not right Uh This rust live coding stream though. It is not specific to this particular Voting topic labels here. The basic idea is that users uh rank the Candidates through which they would which is linked to our crr And the election is run at stream time to determine Is run before Each stream to determine the topic of the stream since ranked choice voting Let's users specify multiple preferences This process Can then be repeated for the next stream Oh to each users second preferred It's great users rank choice voting to allow users to vote on the next rust live coding stream Uh It is not specific to this particular voting topic being able to label here and there Basic ideas This implementation Is not written to be secure or efficient Um Quite to the contrary Users identify with a self-chosen uh username and uh All that is required to change their ballot in the future To add news to add votes for new streams New stream ideas is Not the same username This means that any user can change any other users Uh ballot Simply by giving their username Don't use this for anything serious to deploy run, I guess, uh sqlite 3 dbs dsqlite in schema.sql Also, uh cargo run Saves will now be available for 8000 And I guess we should also tell them about how inserts work. So To add new candidates for voting Uh insert statements of the following Search into items title body Said done is true is the of the candidate Beautiful beautiful That read me Read me push that's still compiling Oh, I guess I forgot to link to this. I guess this we don't really need anymore. These can go away This can go away We are getting pretty close I guess I should start and watch this Who's going to be the first to vote though? It might be me. I don't know if there's even anyone left at this point It's pretty late in most places But hey, we finished now. I just need this to finish Uh, so I guess I can uh tell you all what it's going to be. It's going to be on The squareplan.com slash live coding. I think I think that's where I put it It's getting too late It is Going to be in live coding, yes So there you will be able to vote and just like pick a unique username like pick your github username or something stupid, right? That way, you know, it's unique Um, and then you should be able to just vote for the ideas that we just added because we're just waiting for this to Finish up now And if you have ideas for things ways to improve this like feel free to send pull requests I am not at all committed to any part of this website whether it's like the way it looks or the way you authenticate or anything Feel free. I would only be excited for that to be the case um Pest generator this brings in a lot of stuff I guess this is probably rocket Maybe our diesel maybe actually I wonder if we can tell oh It's running the screen. All right. Well, it'll be there This is just sort of uninteresting to watch. So I think we're going to end the stream there I guess we have this beautiful image. I'm gonna throw it away. Um If you have ideas for upcoming streams, then by all means like let me know I'm on twitter, of course, and uh I'm now on mastodon as well if you don't want to use like Twitter as a closed platform. That's fine, too um, I had to shut my patreon down, which is kind of sad because of Annoying issues with the us tax regulations given that I'm an international student So I can't really refer to that anymore But I will keep uh people posted both both on mastodon and twitter if they're if you want to hear about upcoming streams And now of course you can use this website to see ideas for upcoming streams and potentially also vote for them um Read me should mention something about aro's impossibility theorem to be pretentious Just submit a pr and I'll consider it But it is kind of funny when these things are pretentious in that way I do think it's interesting though because random, um, random choice voting rank choice voting Just happens to fit this particular use case really well because you You have the ability to just vote once for many ideas, right? It's supposed to these constant twitter polls um But yeah, okay, I think we'll end things there Reach out if you have ideas Go to this url in like 10 15 minutes, or if you're watching this later probably straight away And like vote for the ideas and and what you would like to see And send me a suggestion if you have other things and I will happily add it to there um I guess we're gonna Uh, I guess we're gonna end it there. Uh, thanks for those of you who sort of came up with this sort of weird hour to watch um The saturday stream on tokyo Is going to be at the normal time of noon, uh, eastern standard time It'll also be much less programming So the idea is just to go through the design of tokyo and of futures how they execute look at async await Do a lot more of just like More explicit explanatory stuff. Uh, hopefully it'll be interesting. Uh, and I guess I'll see you you all there Um, happy, uh, happy thursday, so to speak Bye