Who Are You?

Cameron Kingsley
5 min readOct 4, 2021

“Who Are You?” is a simple single page application designed to help generate character backstories for role playing games. (i.e., Dungeons & Dragons, tabletop games, etc.) This app utilizes a JavaScript frontend and Rails backend API. One of the top priority design criteria was a simple user interface, the user begins by entering a character name, submitting, and is then presented with a series of multiple choice prompts to answer. Finally, a written story for that character is presented, based upon the answers to the questions. If a user is unsure of an answer, they may also use a random dice roll feature available to select a random answer for the current question.

One of several questions presented to the user, select an answer or select the ‘Roll’ to pick a random answer.

The inspiration behind this app draws from recently starting my first D&D campaign and struggling to develop a background for my character. The problem to solve was helping new players create their background story and provide prompts to quickly create interesting stories. The overall concept was to provide multiple choice questions for the user to answer and in the end, provide them with a written backstory they can take away and use in their game.

Project structure

This architecture of this project includes a JavaScript frontend and a Rails backend set up as an API. The heavy lifting is performed by the JavaScript & CSS, with the Rails API feeding and persisting data on the characters selections and questions to answer.

Backend

The Rails side of things contains a database with three tables, one to store the questions, each record has six responses to select from, and 6 corresponding phrases that are used to populate the final story. This table will not have any user changes and is only used to supply the frontend with question data. The next table is a character’s table. This one is populated by each user starting a new character round. There are columns for each question and which number response they selected. The final table is a ‘response’ join table that ties the characters selections to the corresponding phrase that should be used to populate their story. When the ‘/character/#id’ URL is visited, the API will return the characters info, as well as the response phrases to be used.

Frontend

The frontend is primarily JavaScript with CSS styling. This handles the display and sequencing of the questions shown throughout the several different rounds. A character class is implemented and used to store the character info locally as the questions are answered. Once the final question is answered, a fetch() is performed to the API to save the characters info and receive the returned phrases for use in the final rendering of the story. For the final rendering, a series of asynchronous setTimout() functions are used to create a slowed animation of each phrase writing itself out.

Project Approach

My approach to this project took a departure from my typical backend-forward workflow. I initially spent time mocking up the page and determining what features, functions, and data need. After I had a solid foundation of the specific requirements, began setting up the backend database and rails side of the app, configuring the API routes, data validations, character and question models. Once this was roughed out, I began with the front end and started working with JavaScript to implement the app logic. Starting from the start screen and working my way progressively through the app I added each feature one by one, focusing on function over form at this point with only basic CSS styling. After I made a pass through the whole app then I returned to refactor code, add more specific styling and additional features to the program.

Successes

Overall, I am happy with the result of the project. The greatest success was creating an intuitive and simple user interface, made possible by implementing the JavaScript and use of asynchronous functions. I was able to successfully create and implement both front and back ends and allow them to communicate with each other. This is a really rewarding feeling being able to continually build on the previous lessons in the school program and start bringing it all together.

One of my favorite features is the dice roll button to generate a random selection. This was implemented using a for loop with an incrementor and modified using a multiplier. This incrementor was used to set the delay in a setTimeout() function to loop through and show a rapidly changing random number between 1–6. (along with corresponding dice image) Using asynchronous functions and incrementor modified with a multiplier created the illusion of a fast changing number at first, and decreasing in speed until the loop stops on a number. Once a number is selected, the “submitResponse()” function is called passing in the random number as the selection. The program then carries on to the next question.

Challenges

My biggest challenge was setting up the fetch and communication between front and back end, specifically getting the data in the correct JSON format to be used by either end. I feel this was mostly due simply to the learning curve and this being my first proper project with this implementation. Eventually I conquered it by referring to the previous course documentation to ensure I fully understood the material and wasn’t wasting too much time with trial and error.

Another challenge I face was keeping the code clean and using helper methods to my advantage. My first pass through the program I focused more on getting everything working, but the code was not DRY. There were either several sections of repeated code, or functions that grew to be unruly and violating the single responsibility rule. After everything was functional, I then took the time to run back through my code and break out helper functions to remove repeated code, as well as split up functions into more manageable (and readable) blocks. I was able to refactor and eliminate several functions altogether by reusing and modifying previous functions. One example was the ‘submitResponse()’ function could be called from either a user selecting an answer or submitted by the random dice roll calling the same function.

Conclusion

If I were to create this project again or continue to iterate on the design, I would focus on simplifying my code and make it more concise & DRY-er. I would like to implement a class object for the responses as these are page elements with consistent properties repeated many times throughout the project. I am proud of this project but also realize that I have a long way to go in my development career. I am greatly looking forward to the next project and to keep practicing!

--

--

Cameron Kingsley
0 Followers

Budding software engineer & game developer, jack of all trades with background in construction, fabrication and engineering. Always looking to learn new things