HI THERE!
I'M BLAIR

If you're reading this, I probably applied to a position that you are looking to fill. How exciting for us to be on this journey together! (Just kidding, I'm normal.)

I'm a front-end engineer who has been working full time in the industry since 2017. I love working with CSS/SCSS, am a JavaScript expert, including it's various frameworks, and also well versed in PHP/Laravel, among many other languages and technologies. As a former designer, I love working closely with them, and am able to speak their language and understand design files in a way that eludes many other engineers out there.

When I'm not meticulously arranging my stylesheets, I like rock climbing (indoors and out), going to shows, generally enjoying the Southern California nature and weather, and hanging out with my cat.

Here's My Resume

SKILLS

  • Languages: HTML, CSS/SaSS, Javascript/Typescript, PHP
  • Front-end: Angular, Vue, React, Tailwind, Webpack, jQuery
  • Back-end: Node.js + Express, Laravel
  • Databases: MYSQL, PostgreSQL, MongoDB
  • Workflow: Github, Bitbucket, Jira, Asana, Trello
  • Design: Adobe Creative Suite, Canva, Wire-Framing

REFERENCES

"Her background in design always shines through in her projects and influences her coding decisions in a natural, positive way."
- Zach Totta, Software Engineer
"Blair consistently impresses me with each project she completes; they not only look amazing, but function perfectly as well. The unique ideas she presents reflect her artistic and creative character."
- Tin Tran, Full Stack Developer

CASE STUDY

In 2016, when I was just a baby engineer, I built a clone of the classic Nokia game, Snake, with an 8-bit spin. I thought it would be a fun challenge to refactor it, and also a good way to show off how my skills have improved in the last 8 years in the industry. My original version was pretty good for someone who was semi-new to coding, but there were definitely improvements to be made. (When are there not?)

The main changes were:

Play my version of Snake here, or read on for a more detailed overview of my refactor process.

One of the main changes involved MATH (everyone's favorite), so let's get that out of the way first. Because of the nature of Snake, the game functions on a grid. The snake is broken up into square units, which were originally hardcoded to be 5px square, and the gameboard width and height were hardcoded to be 480px by 320px (also divisible by 5). Since hardcoding pixel units is generally *frowned upon*, I updated my code to have the pixel unit stored in a variable called basePixelUnit with an initial size of 10px.

This variable is used throughout my code to set the gameboard size on mobile, snake size, and food size, as well as in the functions tracking the snake's movement, food eating, and size increase due to food eating. The pixel unit is technically hardcoded in a variable, but now the size can be changed by updating that single variable instead of updating things throughout in the codebase. This change also enabled me to easily scale the game to fit on a smaller/mobile screen, as you can see in the setCanvasSize function below.

screenshot of code showing basePixelUnit variable screenshot of code showing canvas size function

Ok enough math, let's get into the styling. By switching to SCSS and adding Tailwind, I was able to cut my stylesheet length from 139 lines down to 61! One of the other main changes I made was making the game work on mobile/touchscreen. Because my first version of the game relied on the keyboard to play, it did not work on modern touchscreen phones. I built and styled custom onscreen arrow keys with a simulated keypress for touchscreens, which you can see below. I also added a very important pause button and functionality.

screenshot of code showing CSS for custom onscreen keypad
screenshot of Snake game on mobile screen

Another function I always wanted to add was a high score leaderboard! What good is a game if you can't keep track of your high scores? I used the browser's built in localStorage to store and display it onscreen. When Snake loads, it checks localStorage for a highScores key. If it exists, the game pulls in the array of high scores and displays it in the onscreen leaderboard. If there is no highScores key stored, it will create a new empty array that the scores will be saved to going forward. When the game ends, the setHighScores function checks for a duplicate score in localStorage. If your current game score is a unique score *and* in your top 10 scores (for example, if you scored 5 points and there is already a score of 5 in your high scores, it won't save the new one) it will get pushed into the localStorage array and displayed in your top 10 high scores in the leaderboard.

screenshot of code showing high score functionality

To mak things easier on myself, I moved all of my resuable functions into utilities.js. The pickFood function randomly selects 1 of the 3 kinds of food to spawn. The randNum function is used to generate random x,y coordinates for food to spawn, while taking in a min and max (for the gameboard height/width) and taking into account the basePixelUnit (food can only spawn in x,y coordinates that are multiples of 10, or whatever the base unit is set to). The gameReset function is used to easily set and reset the starting values for the game like the snake starting location, the movement tracker, the speed the snake moves at (fps, frames per second), the starting food location, etc. There are a few other things in this file which are pretty self explanatory like isMobileDevice, isTouchScreen, playSound, and increaseSpeed. You can see the full import list in the second screenshot below.

screenshot of code showing utilities functions screenshot of code showing utilities functions

Lastly, my favorite little bit of code is this use of recursion in the randomizeFood function. This function generates random x,y coordinates with the randNum utility function, then uses a for loop to check if the new food location is in a cell where the snake is currently located. If the food *is* located where the snake is, the randomizeFood function is called again recursively until a food spawn location that doesn't overlap with any of the snake's cells in the grid is selected. Now That's What I Call Recursion™!

screenshot of code showing randomizefood recursive function

Wow! We made it. Thanks for joining me on this refactor journey. Don't forget to play my version of Snake! You can see my resume below or see my contact info by clicking the button in the top right. Looking forward to meeting you!

Here's My Resume

SKILLS

  • Languages: HTML, CSS/SaSS, Javascript/Typescript, PHP
  • Front-end: Angular, Vue, React, Tailwind, Webpack, jQuery
  • Back-end: Node.js + Express, Laravel
  • Databases: MYSQL, PostgreSQL, MongoDB
  • Workflow: Github, Bitbucket, Jira, Asana, Trello
  • Design: Adobe Creative Suite, Canva, Wire-Framing

REFERENCES

"Her background in design always shines through in her projects and influences her coding decisions in a natural, positive way."
- Zach Totta, Software Engineer
"Blair consistently impresses me with each project she completes; they not only look amazing, but function perfectly as well. The unique ideas she presents reflect her artistic and creative character."
- Tin Tran, Full Stack Developer