ZAMYLA CHAN: Well, here we are, the last p-set in CS50. Congratulate yourselves from having come so far since your first Hello Worlds and Printing Up Pyramids for Mario. You made a website last week. And we're going to be making another one this week, one that allows you to drive around the Harvard campus, picking up CS50 staff members and bringing them back to their residential houses. Now, last week we worked in PHP, a server side language. For this p-set, we're getting introduced to JavaScript, which is a client side language. So let's take a look at some of the distribution code that's provided to you for this p-set. In the JavaScript folder, there will be a bunch of JavaScript files. There's buildings.js, which contains an array of buildings around Harvard campus with their information and position. Houses.js is an array of Harvard residential houses with their latitudes and longitudes. Passengers.js contains an array of passengers, the CS50 staff members that you'll be bringing back to their residential houses. Math3D.js, that contains a lot of functions to do with the movement. If you're mathematically minded, then I welcome you to take a look. But you don't need to understand everything in there. Shuttle.js, that deals with the Shuttle's movement. And index.html is the home page where everything happens, really, where the user is interacting with the site. Service.css is the CSS style sheet, which in addition to the Twitter Bootstrap Library, controls how index.html looks. And then we also have service.js, which contains service functions for the Shuttle. And here's where you're going to be filling in some of the to-do's. Now let's take a look at objects and associative arrays in JavaScript, which, for all intents and purposes, are interchangeable. If I wanted to make an object a variable called a wand, I would declare it. And inside those curly braces, I would specify, the core is unicorn, the wood is cherry, and the length is 13. Now, I can also access values of objects using associative array notation. So wand index core, I can set that equal to unicorn, or check that if I need. Or I can use the dot operator wand.wood equals cherry, and so on and so forth. So you see that associative arrays and objects in JavaScript are going to be interchangeable, and will come in quite handy. Then we see an array of buildings in buildings.js, again, an array of objects. If I wanted to make an array of the best buildings on Harvard campus, then I would make it as follows. Using this object notation, where I store the root, name, address, latitude, and longitude for every single building object. Let's quickly talk about variables in JavaScript. Like PHP, JavaScript variables are weakly or loosely typed. To create a local variable, you prefix the variable name with V-A-R, var. Now, in JavaScript, functions will limit the scope of variables. So if you have a local variable within a function, then other functions can't access it. But unlike C, loops and conditions don't limit the scope of a variable. So even if you declare it inside of a condition, the whole function will have access to it. Now, without var, the variable will be global. So if you just declare the name and assign a value, then that variable will be a global variable in JavaScript. Now, in houses, we have an associative array of host type objects, where every house is just a latitude and a longitude. Then we have the passengers array, which is an array of object type passenger. So every passenger has a user name, a name, and a house. Notice that I'm saying of type passenger, which really just means that every object has the same key value pairs. So every object of type passenger has a user name, a name, and a house. So what do we need to do for the p-set? Well, we need to allow users to pick up staff members, to display all of the staff members that are currently in our shuttle, and to drop them off. And then we'll also talk about extra features that can be implemented for the Shuttle p-set. But let's talk about pickup first. The faces of CS50 staff have been planted all over campus, where each face is implemented as a place mark on the 3D Earth, and as a marker on the 2D map. So when the user clicks the Pickup button, we want to add nearby passengers to the shuttle. And we also want to remove their place mark from the world and remove their marker from the map, indicating that they're in our shuttle now. So how do we detect if passengers are within range of our shuttle? Well, the function distance, so shuttle.distance, passing in the latitude and longitude, will calculate the distance from the current position of the shuttle to the point that you specify with that given latitude and longitude. So you can use this to calculate the distance from the shuttle to the passengers. But how do you know where the passengers are? Well, that's where we'll have to edit the populate function. Populate places all of the staff members in passengers into the world and into the map, but doesn't store their location. So perhaps you can store their place marks and markers in some global array. Now, there already is a global array storing information from passengers. The passengers array stores each passenger's name and their house. So maybe you can add a few parameters there to the passenger objects. To help us detect all of the passengers within range of our shuttle, let's loop through all of the passengers in the passengers array. A for loop in JavaScript might look something like this, very similar to those for loops in C. Or we can use an alternative for loop structure, for var i in array, where i will still be the index, but you don't need to specify the array.length condition and i++. Every passenger's location is given by their place mark. But the place mark isn't the latitude and the longitude. We have to access those parameters by getting the geometry, using get geometry on the place mark, and then once we have the geometry, getting either the latitude or the longitude using those functions. So now we know how to detect whether passengers are within range of our shuttle. Once we have those passengers, we'll want to add any passengers that are within that range. We want to allow them to hop on and take a seat on our shuttle, but only if we have enough room to them. The shuttle.seats array will indicate whether seats are empty, or who's in that seat. So if a seat is empty, then that seat will be null. So iterate over the seats array, checking for empty seats, storing passengers into those seats until you don't have any more empty seats. And unfortunately, any other passengers will have to wait for the next time the shuttle comes down. Once they get on the shuttle, we'll want to remove their place mark, which is their photo in the 3D world. If I wanted to remove a place mark p, then I would get all of the features from my Earth, from the Google Earth, and then remove that specific place mark using the removeChild function. Then lastly, let's remove the marker, the icon on the 2D map, for any passenger that we are picking up. To remove a marker m, then I'll just execute m.setMap null. Do this for any passengers within range, and you've finished pickup. The chart function should display all of the passengers that are in your shuttle, and empty seat if empty. So chart should iterate over shuttle.seats, displaying the passenger information for every index, and empty seat if that index is null. Now if HTML text is put inside of a JavaScript variable, then by using document.getElementByID, chart can edit the inner HTML of that given element by assigning the HTML text to the document.getElementByID inner HTML variable. When the users click the Drop Off button in index.html, it'll call the dropoff function. And it's our job to implement that. In dropoff, we'll want to remove any passengers from the shuttle only if we're in range of their destination, their residential house. So dropoff will have to check whether the shuttle is in range of any of the houses, and remove any needed passengers from the shuttle. So how do we check if we're in range of any houses? Well, yet again, we'll make use of the shuttle.distance function, passing in the latitude and longitude of the point that we're checking against. But what are those points? Well, the houses array, if you remember in houses.js, stores the latitude and longitude of each house in an associative array, where every index is the name of that house. Then to remove passengers-- well, only if we're in range of their house that they want to go to. So again, remember that passengers stores the house that every passenger wants to go to. If they are within range of their house, then we'll remove that passenger from shuttle.seats and set their position in the array to null. Now let's talk about some extra features that can be implemented in the CS50 Shuttle p-set. There's a point system whereby you keep track of how many points a user has. For dropping off passengers successfully, they can get points. But for trying to drop off passengers where there isn't any house nearby, well, they can get penalized for that. So perhaps you want to keep track of the points in a global variable. You can implement perhaps a timer, where the user has a certain amount of time to pick up and drop off a certain number of passengers. Maybe even integrate this with the point system. Or you can Edit Chart such that passengers are sorted by house. So that would probably be a sort function to shuttle.seats. You can implement a flying feature, where if the user inputs the Konami code, then the shuttle lifts off the ground and the shuttle can fly. But for a safe drop off, best to make the shuttle land its wheels on the ground first. You can also implement teleportation, where you make a drop down list of buildings in index.html. And selecting one of those, the user will be transported to that building on campus. OK, though, to travel through the walls of some buildings on your way there. You can also change the speed of the shuttle, allowing the user to increase or decrease the speed. Perhaps you want a global variable to keep track of how much fuel the shuttle has, decreasing it as you go along. Once you hit zero, though, the shuttle won't be able to move unless you've refueled, perhaps using a button, or even make your own gas station. But that certainly isn't an exhaustive list. Check out the spec for the full list, or perhaps propose your own to your TF. The sky is the limit. This is your last CS50 p-set, so have fun with it. This was CS50 Shuttle. I've got to say, it's been a pleasure making these for you with the production team. And I hope that you've enjoy them, as well. My name is Zamyla. And this was CS50.