Skip to content

A website that allows users to create mazes and post it to others. Players can race to complete the maze and try to make it on the high scores.

Notifications You must be signed in to change notification settings

kricheso/gridlock

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Gridlock

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.

Contents

Terminal:

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
  1. Start the emulator with firebase emulators:start --only firestore.
  2. Run the tests with npm test (ignore the firebase tests since they're out of date).
  3. Login.
  4. Click on the play page, submit a score and verify that your score is in the leaderboard.
  5. Click on the explore page, verify that the cards load.
  6. Click on your profile page, verify that your profile information and games load.
  7. Click on one of the cards, and verify that you can visit a profile of a liker.
  8. Like a game on the explore or
  9. Create a game.
  10. Repeat all of the above steps after logging out.
  11. Verify that the lock on the homepage is locked when logged out, and unlocked when logged in.

Commands to Add a New Feature:

$ 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.

Other Useful Commands:

  • 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 with git 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.

Common Issues:

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 Infinity
  • solveTime - 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>'; 

Authentication.currentUser()

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.

Example usage:

async function myFunction() {
  const user = await Authentication.currentUser();
  if (user === null) { /* user is not logged in */ }
  console.log(user);
}

Authentication.logIn()

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.

Example usage:

async function myFunction() {
  const user = await Authentication.logIn();
  if (user === null) { /* error */ }
  console.log(user);
}

Authentication.logout()

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.

Example usage:

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:

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:

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.

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);
}

About

A website that allows users to create mazes and post it to others. Players can race to complete the maze and try to make it on the high scores.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published