May 7, 2019

Building a web app to rank my favorite Marvel superhero movies, part I

How's a superhero fan supposed to overcome recency bias in rating their favorite movies? Uh, how does complicated math sound?
"A cartoon drawing of a single figure facing and looking questiongly at a line of marble statues of superheroes, both men and women, some with capes, in a museum, lined up horizontally against a single wall, landscape, line drawing, mostly white, simple, bright" by Midjourney

I love superhero movies. Specifically, Marvel superhero movies. Specifically specifically, Marvel Cinematic Universe movies — Iron Man, Captain America, Thor, and so on. Never thought I'd be that guy, but somehow I've seen every single MCU movie — 22 in total.

Why? Because they're super good! There's a reason they have an average Rotten Tomatoes score of 84%.

But which ones are the best? This is a constant debate among my friends. And with the latest phase of the MCU coming to a close with Avengers: Endgame, it's been a good time to take stock and make best-of lists.

I'm Andrew McGill, a product builder who turns delightful ideas into real things.

I used to make stuff at The Atlantic and POLITICO. Now I build things with people like you.

A few problems, though:

  • There are too many movies. Organizing 22 films in order of preference is a... tall order. (🥁) You have to keep track of every other movie when you're considering one, or chunk them in ways that could lead to misalignment later.
  • You're probably going to give better scores to movies you just saw. Because I watched Avengers: Endgame more recently, I'm more likely to rate it higher than the original Avengers, just because I remember more details about it.
  • You probably know your favorite and least-favorite films, but nothing in between. This is a twist on the well-documented recency/primacy effect, where humans are better at remembering the beginnings and ends of lists than things in the middle. In this case, fans probably never formed opinions on middling movies, focusing on just the best and the worst.

All of these problems mean tools that let you drag around movie names probably aren't helping you come up with a definitive list. They're just confusing you!

My take: It's easier to pick your favorite movie when you just have two options in front of you. If you run through enough pairings, eventually you'll get an ordered list.

That's the idea behind mcu.ninja, a ranking tool I put out last week. 🎉

In this post, I'm going to explain the logic behind the ordering algorithm powering mcu.ninja and the command-line utility I built to demonstrate it. Next week, I'll discuss the UI and why I thought Tinder-style swiping was the right decision.

If you just want my MCU movie ranking, here you go.

Sorting is hard

If you need to order a list of 22 items, it's simplest to go one by one and compare every movie to every other.

Let's say I start with Captain Marvel. I'd compare it to Iron Man, the first film in the MCU.

Movie posters of Captain Marvel and Iron Man

OK, that's easy — I like Iron Man better. But that's only the beginning. I still have to compare Captain Marvel to every other MCU movie — 21 comparisons in all.

Captain Marvel vs. every other Marvel movie — quite a few!

Once we're done with Captain Marvel, we move on to the next film: Avengers: Endgame. Since we already compared it to Captain Marvel, we don't have to match them again. But we still have 20 other movies to compare.

41 movie posters
Let's add in Avengers: Endgame. SO MANY MOVIES

So far, we've made 41 comparisons. If we add just two more movies, we're up to 78:

78 movie posters
This is obviously crazy.

Taking this to its mathematical conclusion, we'd have to make comparisons equal to 21 + 20 + 19 + 18... + 1, or (n^2 + n) / 2. That's 231 match-ups — only marginally better than watching 14,000,605 alternative futures.

Quicksort to the rescue

There are plenty of better ways to sort stuff. In this case, topping the list is the Quicksort algorithm.

Let's line up all the movies by date released — the order doesn't matter — and randomly pick Captain Marvel to start:

All the Marvel movies lined up, with Captain Marvel highlighted.

Captain Marvel is the pivot. Our job is to re-order the list so every movie that's worse goes on the left, and every movie that's better goes on the right.

It doesn't matter what order we put them in — only that they're better or worse than the pivot.

We've sorted the movies to be better or worse than Captain Marvel.

Ater sorting (your choices might be different!), we now know Captain Marvel is No. 16 on list. To do this, we had to make 21 comparisons — same as we did before. But the next step is different. We consider the better-than and worse-than movies as their own sets, and run the method again.

So in the "worse-than-Captain Marvel" set, we randomly choose Thor: The Dark World as our pivot. In the "better-than-Captain Marvel" set, we choose Captain America: Civil War. For each of these sets, we again sort the movies by whether or not they're worse than the pivot.

A long of movie posters, sorted.

Now we have three movies properly ordered — with only 40 comparisons, instead of 60 with our previous method. That's a huge improvement.

That kind of efficiency isn't guaranteed. Quicksort works best when the pivots land in the middle of a given set — in this case, the movie that's chosen is average, not terrible or spectacular. But unless you're really unlucky, Quicksort will work far better than brute force.

Building a proof of concept

Before I built out the full mcu.ninja app, I wanted to make sure this method actually made sense. In practice, would it work to present people with pairs of movies and having Quicksort figure out which to show next?

So to test, I built mcu-rankings-cli, a command line interface script written in Node.

Pretty simple — it gives you two options, and you pick one. On the back end, I wrote a MovieList class that handled making match-ups and accepting votes from the user. On the front end, the inquirer makes the CLI magic happen.

The method seemed to work pretty well. Sometimes the pivot movies weren't great — it's annoying to get a stinker like The Incredible Hulk and have to vote against it 20-something times. Later on, I decided to use Rotten Tomatoes data to choose the most "average" movie in a set as the pivot.

But otherwise, success. Next week, I'll talk about how the final swipe-y UI came to be!

For the record, here's my list:

  1. The Avengers
  2. Iron Man
  3. Guardians of the Galaxy
  4. Thor: Ragnarok
  5. Avengers: Infinity War
  6. Captain America: The Winter Soldier
  7. Captain America: Civil War
  8. Avengers: Endgame
  9. Black Panther
  10. Spider-Man: Homecoming
  11. Iron Man 3
  12. Captain America: The First Avenger
  13. Captain Marvel
  14. Ant-Man
  15. Avengers: Age of Ultron
  16. Doctor Strange
  17. Ant-Man and the Wasp
  18. Thor
  19. Guardians of the Galaxy Vol. 2
  20. Thor 2
  21. Iron Man 2
  22. The Incredible Hulk
Whatever you’re looking to build,
I’d love to chat. Drop me a line.