(Note: I'm moving my posts from my time at Flatiron School from my Github to this platform. This blog entry was first posted on April 21, 2020)
Animal Crossing: New Horizons is a game in which you play a human who moves to an island inhabited by anthropomorphic animals. One aspect of the game is to collect fish and bugs that come out at different times of the day/year and donate them to the museum. You can also sell these creatures and some are worth a ton of bells (that’s the in-game currency). It’s a pretty cute, chill game and it couldn’t have come out at a better time, with all the highly stressful things happening right now between a pandemic and upcoming job hunt.
For my final project I wanted to make something that I could use ASAP. I decided to make an app that would tell me exactly which creatures are around to catch at the current date/time, and I wanted to be able to sort it so I can know what to look for that’s worth the most money. I also wanted to be able to create an account so I can keep track of everything I’ve already caught and handed in to the museum.
Before I could do anything I needed to grab the data about each creature from the animal crossing wiki. I wrote a scraper in Ruby, using nokogiri, for this.
Next, I needed to be able to store the data in a database. I created a Rails api project and a few database migrations. I created a Creature to hold most the information about each creature, such as name, type, price, location, etc. Initially I also had columns for time, start_time, and end_time. However, there were 3 or so creatures that were available for a few hours in a day and would then be available for a few more hours that same day. I ended up having to create a separate table called Availables to store the time, start_time, and end_time, and another join table for Availables and Creatures.
Since the game also has you select which hemisphere of the world you’d like your island in (northern or southern) I had to create another table called Hemispheres, which contained columns of boolean values for each calendar month. Each creature needed to be joined with their values for both hemispheres.
Once I had all of the creatures scraped into my database I began writing a bunch of scope methods. I had a lot of fun with this, chaining methods together and returning all sorts of information, but unfortunately couldn’t use most of these methods since I didn’t want to be doing a new fetch request every time I clicked a sort button or something on the front-end. The methods I did use, however, were for grabbing every creature that was currently available. I created methods to check a creature’s hemisphere and times and returned whichever matched the current date/time.
The time thing was tricky. The scraped time data returned values such as “All day”, “9am - 4pm”, or ‘9AM - 4PM’ and I couldn’t really compare that to the current time, so I decided to convert them to military time. If a creature was out all day I set its start_time to 0 and end_time to 23. For the other creatures I first fixed the formatting of results in lowercase, and then converted all their times based on the ‘AM’ or ‘PM’. To check against the current time, after much trial and error getting the logic right, I used
.between?. If a creature’s time was something like ‘7PM - 4AM’ I had to create a day variable to set the creature’s end_time into the next day.
def is_available_at_this_time? return true if self.time == "All day" # set time instances for start & end times based on current time for comparison ct = Time.now start_time = Time.new(ct.year, ct.month, ct.day, self.start_time, 0, 0, Time.now.utc_offset) # if start time < end time then it goes into the next day et_day = self.end_time < self.start_time ? ct.day + 1 : ct.day end_time = Time.new(ct.year, ct.month, et_day, self.end_time, 0, 0, Time.now.utc_offset) ct.between?(start_time, end_time) end
After I had all the creature stuff taken care of I created a User table to store a username and password, and a join table for users and the creatures they own.
On the front-end, I set up a Redux store with a few reducers: CreatureReducer to add creatures, userReducer to set and clear the current user (logged in) and add/remove creatures that the user owns, and an appReducer that keeps track of the current page. There might be a better way to go about this, but I needed an easy way to know if I was on the home page, displaying currently available creatures, or a user’s page, which displays all creatures as well as a couple of other differences, since both use the same creature displaying components.
On the home (currently available creatures) page I also display a clock with the current date and time. I intend to expand upon this in the future and have the clock update in realtime and re-render the creature list if new creatures are out when the hour changes over.
There is a rumor that more types of creatures will be added to the game, so if that's the case I will be updating my scraper so I can add those types in. I'm thinking about expanding to keep track of other collectibles in the game as well.