Gridlock is a maze game built in React where players must visit every cell of the game board exactly once. This project aims to create an online version of that game where users can create mazes and compete for fastest solver.
- How to run Gridlock on a localhost
- How to verify a release
- GitHub Help
- Objects
- Authentication.js
- Firestore.js
To run Gridlock, open the terminal and navigate to a directory:
$ cd desktop
Clone the repo:
$ git clone https://github.com/kricheso/gridlock.git
Navigate into the repo:
$ cd gridlock
Install Firebase tools as an administrator:
$ sudo npm install -g firebase-tools
Install Firebase:
$ npm install firebase
Look in your email for the firebase.txt
file. Rename the file from: firebase.txt
to firebase.js
then move the file into the following directory:
/gridlock/src/
Start the localhost server:
$ npm start
- Start the emulator with
firebase emulators:start --only firestore
. - Run the tests with
npm test
(ignore the firebase tests since they're out of date). - Login.
- Click on the play page, submit a score and verify that your score is in the leaderboard.
- Click on the explore page, verify that the cards load.
- Click on your profile page, verify that your profile information and games load.
- Click on one of the cards, and verify that you can visit a profile of a liker.
- Like a game on the explore or
- Create a game.
- Repeat all of the above steps after logging out.
- Verify that the lock on the homepage is locked when logged out, and unlocked when logged in.
$ git clone https://github.com/kricheso/gridlock.git
$ cd gridlock
$ git checkout -b name_of_feature # Creates branch.
$ git add edited_file1 edited_file2 edited_file3 # Or do "git add ." to add everything at once.
$ git commit -m "Implement <name of feature>" # Add a readable commit message here.
$ git push
Now go to the github website to send a pull request to merge your branch.
$ git checkout master
$ git pull # Pull updates from github before implementing next feature.
git status
- Show what files were changed or added to commit.git log
- Show the commits on the active branch.git diff
- Display local file changes.git diff --staged
- Display changes that were marked ready to commit withgit add
.git branch
- Show active branch.git checkout branch_name
- Switch to an existing branch.git reset --soft HEAD^
- Undo the last commit without losing changes.
If you get a merge conflict involving package-lock.json or package.json, just copy the versions of those files from github, then reinstall any packages that you've added. This is faster since these files are pretty verbose. So for example:
# Overwrite files with what's on Github:
$ git checkout master -- package.json
$ git checkout master -- package-lock.json
# Replace this library with whatever you've installed to make your changes work.
$ npm install @material-ui/core
Gridlock has three main objects: Grid, Score, and User objects.
created
- A date that corresponds to the time and date the grid was created.creatorDisplayName
- A string that is the creator's display name.creatorId
- A string that is the creator's userId.data
- A character matrix that represents the shape of the grid. S means start. F means finish. Numbers mean steps left.id
- A string that is the id of this grid.liked
- A boolean that represents if the current user liked the grid or not.numberOfAttempts
- A number that is the equal to the sum of numberOfIncompletes and numberOfCompletes.numberOfCompletes
- A number that represents the number of attempts that were successful.numberOfIncompletes
- A number that represents the number of attempts that were unsuccessful.numberOfLikes
- A number that is the number of likes this grid has.solution
- An integer matrix that represents multiple coordinates of the solution. Each element in the array is an array of length 2 that represents a coordinate.title
- A string that is the title of this grid.
created
- A date that corresponds to the time and date the score was created.gridId
- A string that represents the grid id the score was scored on.id
- A string that is the id of this score.isComplete
- A boolean that determines if solveTime equals InfinitysolveTime
- A number that represents the time it took to solve in milliseconds.userDisplayName
- A string that represents the display name of the user who scored this score.userId
- A string that represents the userId of the user who scored this score.
created
- A date that corresponds to the time and date the user was created.displayName
- A string that corresponds to the user's name.email
- A string that is the user's email.id
- A string that is the id of this user. Id is equal to email.numberOfFollowers
- A number that represents how many people follow this user.numberOfFollowing
- A number that represents how many people this user follows.numberOfTotalLikes
- A number that equals the sum of likes on all the user's grids.photoUrl
- A string that is the url link for the profile image.
Authentication.js is a custom authentication class that allows you to access the user object that you logged in as. All methods in this class are asynchronous and static. Make sure to import the file like this:
import Authentication from '<path>';
Returns the user object that someone is currently logged in as. Return null if a user is not logged in.
- Returns:
User?
- A user object.
async function myFunction() {
const user = await Authentication.currentUser();
if (user === null) { /* user is not logged in */ }
console.log(user);
}
Displays a sign in screen and returns the user object that someone logged in as. If you do not have an account, it will create one automatically. If the log in fails, it will return null.
- Returns:
User?
- A user object.
async function myFunction() {
const user = await Authentication.logIn();
if (user === null) { /* error */ }
console.log(user);
}
Logs the user out. If the log out succeed, it will return true. If the log out failed, it will return false.
- Returns:
boolean
- True or false.
async function myFunction() {
const success = await Authentication.logout();
if (!success) { /* error */ }
console.log(success);
}
Firestore.js is a custom database class to make communications to Google Firestore easier and less error-prone. Almost all methods in this class are asynchronous and static. There are four main method types: Add Methods, Get Methods, Hash Methods, and Remove Methods. Make sure to import the file like this:
import Firestore from '<path>';
ADD methods add data to Google Firestore. These methods will either return the object
added or null
on failure. Here is a list of things you can do:
- Add a User to Someone's Follow List
- Add a New Grid
- Add an Incomplete Score to a Grid
- Add a Like to a Grid
- Add a Score to a Grid
- Add a New User
Simulates a user following another user.
- userId
String
- The user id of the person that wants to follow someone. - followingId
String
- The user id of the person being followed. - Returns:
Follow?
- The follow object that was created.
Example usage:
async function myFunction() {
const follow = await Firestore.add.follow("[email protected]", "[email protected]");
if (follow === null) { /* error */ }
console.log(follow);
}
Simulates a user creating a grid.
- userId
String
- The user id of the person who created the grid. - title
String
- The title of the grid. - matrix
Character[][]
- The shape of the grid. - solution
Int[][]
- Solution to grid. Each element represents a coordinate in an array of length 2. - Returns:
Grid?
- The grid object that was created.
Example usage:
async function myFunction() {
const createdGrid = await Firestore.add.grid("[email protected]", "My Title", [["S", "0"], ["1", "F"]], [[1,0],[1,1]]);
if (createdGrid === null) { /* error */ }
console.log(createdGrid);
}
Adds a score of incomplete. This method is the same as Firestore.add.score(userId, gridId, Infinity)
.
- userId
String
- The user id of the person who did not complete a grid. - gridId
String
- The grid id that the person played on. - Returns:
Score?
- The score object that was created.
Example usage:
async function myFunction() {
const recordedScore = await Firestore.add.incompleteScore("[email protected]", "My [email protected]");
if (recordedScore === null) { /* error */ }
console.log(recordedScore);
}
Simulates a user liking a grid.
- userId
String
- The user id of the person who liked grid. - gridId
String
- The grid id that the person liked. - Returns:
Like?
- The like object that was created.
Example usage:
async function myFunction() {
const like = await Firestore.add.like("[email protected]", "My [email protected]");
if (like === null) { /* error */ }
console.log(like);
}
Adds a score with a solve time of n milliseconds.
- userId
String
- The user id of the person who played on the grid. - gridId
String
- The grid id that the person played on. - milliseconds
Number
- The time it took to solve the grid in milliseconds. - Returns:
Score?
- The score object that was created.
Example usage:
async function myFunction() {
const recordedScore = await Firestore.add.score("[email protected]", "My [email protected]", 35500);
if (recordedScore === null) { /* error */ }
console.log(recordedScore);
}
Adds a new user to Gridlock. Note: Authentication.js calls this function automatically.
- user
Firebase User
- A Firebase Authentication user. - Returns:
User?
- The user object that was created.
Example usage:
async function myFunction() {
const createdUser = await Firestore.add.user(myFirebaseUser);
if (createdUser === null) { /* error */ }
console.log(createdUser);
}
GET methods get data from Google Firestore. These methods will either return the value
retrieved or null
on failure. If the method returns an array, the order is random unless specified. Here is a list of things you can do:
- Get a Boolean if a Grid Exists
- Get All Users that Follow a Certain Person
- Get All Users a Certain Person is Following
- Get All the Grids Created by a Certain User
- Get All Grids that the Current User Follows
- Get a Grid Object for the Current User
- Get a Grid Object for an Unregistered User
- Get Like Object
- Get Top Five Scores for a Certain Grid
- Get Trending Grids for an Unregistered User
- Get Trending Grids for the Current User
- Get User Object
- Get All Users Who Liked a Certain Grid
Determines if a grid exists. Note: all Firestore functions do this automatically.
- id
String
- A grid id. - Returns:
Boolean
- True if the grid exists. False if the grid does not exist.
Example usage:
async function myFunction() {
const doesExist = await Firestore.get.doesGridExist("My [email protected]");
console.log(doesExist);
}
Gets all the users that follow a certain person.
- id
String
- A user id. - Returns:
User[]?
- An array of user objects.
Example usage:
async function myFunction() {
const followers = await Firestore.get.followers("[email protected]");
if (followers === null) { /* error */ }
console.log(followers);
}
Gets all the users a certain person is following.
- id
String
- A user id. - Returns:
User[]?
- An array of user objects.
Example usage:
async function myFunction() {
const following = await Firestore.get.following("[email protected]");
if (following === null) { /* error */ }
console.log(following);
}
Gets all the grids created by a certain person. The requestor is the user requesting this info (usually the current user). If both parameters have the same ids, a user is fetching a list of their own grids.
- id
String
- The user id of the person's grids I want. - requestorId
String
- The user id of the person requested the data. - Returns:
User[]?
- An array of grid objects.
Example usage:
async function myFunction() {
const grids = await Firestore.get.gridsCreatedByUser("[email protected]", "[email protected]");
if (grids === null) { /* error */ }
console.log(grids);
}
Gets all the grids a user follows. Note: the user must be the current user while logged in.
- id
String
- The id of the user requesting this info. - Returns:
User[]?
- An array of grid objects.
Example usage:
async function myFunction() {
const grids = await Firestore.get.gridsFollowedForUser("[email protected]");
if (grids === null) { /* error */ }
console.log(grids);
}
Gets the grid object for a logged in user. UserId corresponds to the user's id (which is the same as their email address) that is currently logged in. The gridId is the requested grid object. Note: all Firestore functions do this automatically.
- userId
String
- The id of the logged in user. - gridId
String
- The id of the grid. - Returns:
Grid?
- The grid object that was queried.
Example usage:
async function myFunction() {
const grid = await Firestore.get.gridForUser("[email protected]", "[email protected]");
if (grid === null) { /* does not exist */ }
console.log(grid);
}
Gets the grid object for a user who is not logged in. The gridId is the requested grid object. Note: all Firestore functions do this automatically.
- gridId
String
- The id of the grid. - Returns:
Grid?
- The grid object that was queried.
Example usage:
async function myFunction() {
const grid = await Firestore.get.gridForUnregisteredUser("[email protected]");
if (grid === null) { /* does not exist */ }
console.log(grid);
}
Gets the like object for the corresponding user and grid. Note: all Firestore functions do this automatically.
- userId
String
- The id of the user who liked a certain grid. - gridId
String
- The id of the grid the user liked. - Returns:
Like?
- The like object that was queried.
Example usage:
async function myFunction() {
const like = await Firestore.get.like("[email protected]", "My [email protected]");
if (like === null) { /* does not exist */ }
console.log(like);
}
Gets the top five scores for a certain grid. This function does not include scores with a solve time of Infinity. The array will be sorted from faster times to slower times.
- id
String
- The id of the grid. - Returns:
Score[]?
- An array of score objects.
Example usage:
async function myFunction() {
const scores = await Firestore.get.topFiveScoresForGrid("My [email protected]");
if (scores === null) { /* error */ }
console.log(scores);
}
Gets a list of trending grids for a user who is not logged in. The max amount of grids returned is 20. The array will be sorted from most likes to fewer likes.
- Returns:
Grid[]?
- An array of grid objects.
Example usage:
async function myFunction() {
const grids = await Firestore.get.trendingGridsForUnregisteredUser();
if (grids === null) { /* error */ }
console.log(grids);
}
Gets a list of trending grids for a user who is logged in. The max amount of grids returned is 20. The array will be sorted from most likes to fewer likes.
- id
String
- The id of the user who is requesting this info. - Returns:
Grid[]?
- An array of grid objects.
Example usage:
async function myFunction() {
const grids = await Firestore.get.trendingGridsForUser("[email protected]");
if (grids === null) { /* error */ }
console.log(grids);
}
Gets the user object for the corresponding user id. Note: all Firestore functions do this automatically.
- id
String
- The id of the user. - Returns:
User?
- The user object that was queried.
Example usage:
async function myFunction() {
const user = await Firestore.get.user("[email protected]");
if (user === null) { /* does not exist */ }
console.log(user);
}
Gets a list of all the users who liked a specific grid.
- gridId
String
- The id of the grid. - Returns:
[User]?
- An array of user objects.
Example usage:
async function myFunction() {
const users = await Firestore.get.usersWhoLikedGrid("[email protected]");
if (users === null) { /* error */ }
console.log(users);
}
Don't know the id? HASH methods can help. All HASH methods are synchronous but keep in mind there are no checks to the database. You must be absolutely sure that the parameters you pass are valid or you might get an id that is not correct. Note: all of these functions are not required becuase it is implemented under the hood already.
- Convert a Grid Data String to a Character Matrix
- Convert a Grid Matrix to a Data String
- Convert a User ID & User ID to a Follow ID
- Convert a User ID & Title to a Grid ID
- Convert a User ID & Grid ID to a Like ID
- Create a UUID
- Check if a Character Matrix is a Valid Grid Matrix
Converts a grid data matrix to a grid string matrix.
- matrix
Character[][]
- The character matrix of the grid data. - Returns:
String?
- The grid data in string form.
Example usage:
function myFunction() {
const dataString = Firestore.HASH.convertToGridDataString([["S", "0"], ["1", "F"]]);
if (dataString === null) { /* error */ }
console.log(dataString);
}
Converts a grid string to a matrix.
- id
String
- The grid data in string form. - Returns:
Character[][]?
- The character matrix of the grid data.
Example usage:
function myFunction() {
const dataMatrix = Firestore.HASH.convertToGridDataMatrix("S10-01F");
if (dataMatrix === null) { /* error */ }
console.log(dataMatrix);
}
Converts a two user ids to a follow id.
- userId
String
- The id of the user that is following someone. - followingId
String
- The id of the user that is being followed. - Returns:
String?
- The follow id.
Example usage:
function myFunction() {
const followId = Firestore.HASH.convertToFollowId("[email protected]", "[email protected]");
if (followId === null) { /* error */ }
console.log(followId);
}
Converts a user id and a title to a grid id.
- userId
String
- The id of the user who created the grid. - title
String
- The title of the grid. - Returns:
String?
- The grid id.
Example usage:
function myFunction() {
const gridId = Firestore.HASH.convertToGridId("[email protected]", "My Title");
if (gridId === null) { /* error */ }
console.log(gridId);
}
Converts a user id and grid id to a like id.
- userId
String
- The id of the user who liked the grid. - gridId
String
- The id of the grid. - Returns:
String?
- The like id.
Example usage:
function myFunction() {
const likeId = Firestore.HASH.convertToGridId("[email protected]", "My [email protected]");
if (likeId === null) { /* error */ }
console.log(likeId);
}
Creates a UUID.
- Returns:
String
- A UUID.
Example usage:
function myFunction() {
const uuid = Firestore.HASH.createUUID();
console.log(uuid);
}
Determines if a data grid matrix is valid.
- Returns:
Boolean
- True if valid. False if not valid.
Example usage:
function myFunction() {
const isValid = Firestore.HASH.isValidMatrix([["S", "0"], ["1", "F"]]);
console.log(isValid);
}
REMOVE methods remove data to Google Firestore. These methods will return a boolean. True on success and false on failure. Here is a list of things you can do:
Simulates a user unfollowing another user.
- userId
String
- The user id of the person that wants to unfollow someone. - followingId
String
- The user id of the person being unfollowed. - Returns:
Boolean
- True if successfully deleted. False if failure.
Example usage:
async function myFunction() {
const success = await Firestore.remove.follow("[email protected]", "[email protected]");
if (!success) { /* error */ }
console.log(success);
}
Simulates a user deleting (hopefully their own) grid. Deletes all likes and scores. The creator will lose likes from their total number of likes.
- id
String
- The grid id of the grid to be deleted. - Returns:
Boolean
- True if successfully deleted. False if failure.
Example usage:
async function myFunction() {
const success = await Firestore.remove.grid("My [email protected]");
if (!success) { /* error */ }
console.log(success);
}
Simulates a user unliking a grid.
- userId
String
- The user id of the person who unliked grid. - gridId
String
- The grid id that the person unliked. - Returns:
Boolean
- True if successfully deleted. False if failure.
Example usage:
async function myFunction() {
const success = await Firestore.remove.like("[email protected]", "My [email protected]");
if (!success) { /* error */ }
console.log(success);
}