DEV Community

Cover image for Let's not over-engineer things
Nonsoo
Nonsoo

Posted on

Let's not over-engineer things

Not too long ago, I created a game called clueless words -- a daily word game where users use a list of synonyms to a word to find the secret word for the day. I'm fully biased here but I would say it's quite fun to play every day.

One of the things that I had to think about when creating the game was how new words were going to be generated every day. More specifically, was there a way to pick a word from a list and then have this done daily? To be fair after taking a closer look into how to go about solving the problem, numerous solutions started to pop up. I was looking for the most optimal solution though; After all, just because there is a solution to a problem doesn't mean that it is the most optimal solution. Let's think about the problem -- we want a way to generate a random word every day when a user visits the website. How do we do this? We're going to be going over some solutions and then I'll walk you through the implementation of my solution.

Option 1

People have dedicated their time to making APIs that generate random words when that API receives a request. This is one part of the problems solved and we can use this in our game, however, it opens up another problem. How do we make this API request recurring? We need new words every day so we would need a way to tell the server to generate a new word on a new day. One option would be to set up what is known as a CRON job.

CRON is a job scheduler that is set up on a Unix-like machine where users set up and maintain software environments that run periodically at fixed times, dates, or intervals. Therefore, CRON is most suitable for scheduling repetitive tasks.

The CRON job would be responsible for calling a serverless function that makes an API request to the random word generator API and this would occur daily. This solves our problem of generating random words which we can then use in the game but it comes at an extra cost. We now have to determine how we are going to set up a CRON job in the cloud and more importantly, we have to now setup alongside our serverless function.

Another approach is that we gather a list of words and we store it in a database. We can then build an API that increments through our database of words daily. We can also implement our previous approach of working with a CRON job to help us get a new word from our database. This is also a good approach but we now have to worry about configuring a database, building that API and then serving everything.

While these solutions are viable options for solving our problem, these approaches add a lot of complexity that may not be needed. They may be more optimal solutions to our problem.

Option 2

After scouring the internet, listening to a few podcasts, and quite a few days spent trying to come up with a solution, I finally landed on the idea of "Why don't we just index an array of words every day?". We would essentially just store our list of words in JSON form and when a user makes a request to the website the array of words would be indexed to get the word for that day. This is a simpler solution but it also poses another problem -- how do we index an array every day?

What I realized was that the way the index was generated was important and crucial to what word was going to be shown on any given day. In that regard, it would mean that the index generated for the word list would have to become date specific. Essentially the index could represent the time in days that have elapsed from when the game was released -- we call the offset date. Naturally, as time progresses, this offset date would also increase in value day after day. We can then use this offset date to index our array of words and naturally have a new word every day as time progresses. There is no need for any databases, API requests, or CRON jobs as everything in terms of generating new words every day for the game is handled by this function. All we have to do is supply the array, the current date, and the date the game was released to get a new item generated every day.

Although this approach presents its downfalls as the wordlist has to be local, I think it's cool and simplistic in terms of its setup. We're going to be walking through an implementation of the functions in JavaScript, but they can be done in any programming language.

We first have to create our helper function called calculate offset date:

const getOffSetDate = (currentDate, baseLineDate) => {
  const offset = currentDate - baseLineDate;
  const toDaysConverter = 24 * 60 * 60 * 1000;
  const convertToDaysNumber = Math.abs(Math.floor(offSet / toDaysConverter));

  return convertToDaysNumber;
};
Enter fullscreen mode Exit fullscreen mode

This function takes in a currentDate and baseLineDate as its arguments and calculates an offset number by subtracting the baseLineDate from the currentDate. Since the JavaScript data object returns values in terms of milliseconds, our current offset number is in milliseconds. For our next function, we need to get a representation of the time in days, therefore, we have to convert our offset number to days.
Things to note are that we're using Math.floor to ensure that we do not have a decimal value but more importantly to ensure that we are appropriately accounting for one full day. We are then taking the absolute value to ensure that we do not have any negative values.

We now have to create a function that is going to return a single word from a word list that is passed in as an argument.

const getTodaysWord = (WordLst) => {
  const todaysDate = new Date();
  const baseLineDate = new Date("October 02, 2022 00:00:00 UTC");

  const indexArray = getOffSetDate(todaysDate, baseLineDate);

  const todaysWord = WordLst[indexArray];

  return todaysWord;
};

export default getTodaysWord;
Enter fullscreen mode Exit fullscreen mode

Inside our new getTodayWord function, we have to initialize two variables that are going to represent todaysDate and the baseLineDate. We then call our getOffSetDate function, pass in the two variables and then store the return value in a new variable called indexArray. Remember the return value of getOffSetDate is a number that represents that time in days that have elapsed from the baseLineDate. We now use this value as an index for our WordLst to get a single word for the respective day.

Conclusion

YAY!! We've built a way to generate a new word daily without the need for any databases, API requests, or CRON jobs as everything in terms of generating new words every day for the game is handled by the functions above. Although there are still downfalls with this approach, I believe it provides a simple and elegant way of generating a new word/puzzle every day.

Hope you found this useful, don't forget to smash the like button and I'll catch you in the next one... Peace!

Top comments (0)