Next lesson playing in 5 seconds

Cancel
  • Overview
  • Transcript

5.9 Reviewing the Game

The last feature we'd like to add is a game review feature, which will allow users to step through a game after they have completed it. In this lesson, you'll see how our architecture makes that feature simple to implement.

5.9 Reviewing the Game

There's one last feature that we want to build. And that is the ability for users to review their games after they have completed them. So what I have here is a game that has been completed. As you can see, we have andrew won, and we have a hash mark in the last move which means checkmate. So this game is over. There's nothing more that can be moved here. But what if the two players of the game want to review what they did in the game? Why don't we make a couple of buttons where they can step through each move one by one? And because of the way that we're displaying the board and the list of moves, this is actually going to be a lot simpler than you might think. We're going to start in our game.html file. And here we have an h3 where we have moves and just above the actual moveList, let's insert another template which we're going to call stepper. And let's hand it the result. Let's create this stepper template right down here. This is what's going to allow the user to step through the moves that have been made if the game is complete. All right and we pass in the result because we need to know if the game has been completed yet or not, and we do that with the result. So, we have our stepper template here. Let's go ahead and create our stepper at the very bottom of our game.js file. So, we're gonna have template.stepper and let's add the helpers first. And there are two helpers that we need here. First of all, we need to know if the user can start stepping through the game. So we'll call this function canStep. And it's going to take the result as a parameter. What we'll do of course is return true or false, and we'll do this with a binary and. So we'll start with result. Now the first part here result will only be true if the result is a truthy value. Now results can be one of two things we know. It can either be null or it can be a string. A string is truthy, and null is falsely. So if the game is over, meaning results as a string, this part will be true. The next thing we need to know is are we already stepping through the game? And we'll store this in a session variable. A session variable is basically a temporary reactive variable. Now, remember in Meteor, reactive means that our templates will automatically change when a reactive value changes. So we can use the session variables by saying session.get and we'll get the stepping variable. Now of course we haven't set this yet so it will be false at the beginning. And let's say we can step if we are not currently stepping, right? So if there is a result and we are not stepping, then canStep will return true. Now the other one we'll do is just stepping to see if we are already stepping through. And for this we'll just return Session.get stepping. All right, so this should be pretty basic, let's see. If we come back to our stepper template here, let's add two things. So, we'll start with an if block. And we'll say, if canStep. And we have to pass in the results remember. And since we passed the result to the stepper template, we can just say, this which is the value of result. So if we can step, then let's show a button. We'll give it a class of button and btn-primary. And let's give it an ID of step and let's just give this button the text Step Through Game. Once this button has been clicked, we will set stepping equal to true. In which case this canStep will then be false because we are currently stepping so we can't start stepping, right? So this button will disappear. Now we will have if stepping, right? And so once that button is clicked, it will disappear and a set of new buttons will appear. And these are going to be in a button group. So let's create a div here with a class of btn-group. And in here we're gonna put two buttons. So the first button is going to have an id of previous. And, as you might expect, we'll have the class button and also the class button default and inside this button lets put an arrow so we can do ← and then we'll say previous. Let's duplicate this button replace the id with the id next. And then, let's replace the text in the tags here with the word Next, and then we'll have &rarr. And of course, these entities stand for left arrow and right arrow. So now of course, we need some event handlers for all of these buttons, right. So let's say Template.stepper.events. And we have three buttons that we want to manage a handler for. The first one is a click on the button with an ID of step. So we're going to set two session variables in here. We'll say Session.set and we'll set stepping equal to true, as you might have guessed. But then we also need to know what move we're currently looking at. So we'll set the moveIndex, and that's just gonna start on 0, which means before the game begins, right, just kind of the starting point. Okay, now we also want to click on hash previous and this is going to just subtract one from the move index. So let's get the current value of the index, so we'll say var idx = session.get and that will be moveIndex. And then we'll say Session.set. And we'll set moveIndex. And we don't want to be able to go below zero, right? So we'll say if the value is less than or equal to 0, then we'll go ahead and set it to 0. Otherwise, we'll set it to idx -1. So that is our previous function. And lastly, we'll need a click for next. And in here, we're just going to do something very simple. We'll say session.set( 'moveIndex, and we will do Session.get('moveIndex. And we will just add 1 to it. Now you might wonder, well what happens if we go over the maximum number of moves? Well we don't actually know how many moves we have from within this function. However we will from other parts of the code, so we're going to worry about that somewhere else. So we don't have to worry about passing extra values around where they are not absolutely necessary. Okay, so at this point if we come back to the browser, you can see that we now have this Step Through Game button and we have this because the game is over. If we go back to another chess game where the game is not over yet, you can see that we don't have that button displaying. However, in the archive game, we do. So if we click this button, it disappears and we now have next and previous buttons. If we look down here in the terminal, I can say Session.get. And I can get the move index. And you can see that it's 0. Now if I click next a few times, you can see nothing actually changes here. But the move index is now 4, if I click Previous a bunch of times, okay, you can see, we actually get an error, val is not defined. And if we come back, okay, this is probably an obvious mistake that you already saw. We can't check for val less than or equal to 0, we have to check that the index is. Okay, so we know that code's working, but the question now is, how do we use this moveIndex value to actually change our move list and our board? Well, if we go back up to the very top here, where we have our helpers for Template game, you can see that the moves list that is being displayed and the rows that are being displayed are both based on this function getMoves. So let's go do this inside the getMoves function. And this is really why we've written this with this abstracted getMoves function, that up until this point just seems to be duplicating steps. After we load our portable game notation here let's go ahead and check to see if we are currently stepping through the game. So let's say If session.get equals stepping, then we need to slice our list of moves but right now we're just returning our whole list of moves in our history here. So let's actually move that up here. And change this to a moves list that we will return, right. So we get all of our moves and then if we are stepping through this we'll slice some of those moves off and then we'll return the list. So all we have to do is say moves = moves.slice and will slice from zero all the way up to session.get(moveIndex). Now, this should be all we need for most cases. In fact if we come over here and look at this now, if I press step through game. Notice that right away because the move index is zero, we're sent back to the very beginning of the game. And if I press previous, we're not actually counting into negative numbers. Because of the catch that we put into the previous button event handler. If I click next you can see right away, we get the first move, second move, third move, fourth move, fifth move, sixth move, seventh move is the winning move, right? However, if I keep clicking next nothing changes, which is fine, and the behavior we want. However, if I click Previous notice that it doesn't immediately start counting down. I have to click Previous for all of the clicks that I made on next and then finally we get back to our count. So basically what we wanna do is as we're clicking Next, if moveIndex ever gets to be more than the moves that we have, we need to fix that. So let's do this inside our if (Session.get('stepping')). We can make this really easy. We can just say if moves.length, which is all the moves we have, is ever less than Session.get(moveIndex), well, then all we want to do is a session.set and we're going to set the moveIndex equal to moves.length. And that way, we'll never actually have a move index higher than moves.length. Okay, so if we try this again now I'll refresh the page, we can step through one two three four five six seven. I'll click it a few more times but as soon as I click previous, we make one step back, excellent. Okay. So now we have all of the features we wanted to build into our chess application. We are ready to deploy it.

Back to the top