An Epilogue¶

Almost 3 years after opening its doors, Blaseball is closing down for good. As such, these notes have no more reason to see development. They'll stay up as long as GitHub Pages exist (so probably forever), but with no more seasons there's nothing left to analyze. So let's do a post-mortem, not on Blaseball itself (there are much smarter people that could do that better than me), but of these notes.

Last Updated June 4th, 2023


A Brief History¶

I joined Blaseball in Season 2, July 28th 2020, after hearing about it from Felix on Twitter. I remember the post that made me join was something about a player stealing from 3rd Base to Home, a concept so incredibly silly to me from knowing how regular Baseball worked. Turns out by the end of Blaseball that would be incredibly benign. It's just how Blaseball worked. It wasn't afraid of being weird, or breaking rules, especially if it was funny.

I joined the Philly Pies because I had family living there at the time, and because it was the closest team to where I was living (that wasn't Baltimore. Sorry Crabs, as someone from Virginia I have Opinions About Maryland). Even after joining the main site it took me a few days before joining the Discord, because I'm not really a social person. I had never really been in a "fandom" before, at least not enough for me to call myself part of it. But Blaseball was designed as a social game, and it really benefited from being able to talk to other fans on your team about what you were going to do for elections.

Shortly after I joined, this thing called SIBR started up and begun digging deep into Blaseball: cataloging all the API endpoints, figuring out what everything meant, searching for secrets. This got me interested in doing some quick scripting around, so I cobbled together some Python scripts to fetch data from the backend. Unfortunately for me, I was not very good at actual analysis. The process of taking these numbers and turning into something meaningful was just kinda out of my wheelhouse. So I simplified it: just scrape the info and put it somewhere easier to access. This started with the Election Results Sheet, but I eventually started wanting an easily digestible list of the current Election offerings.

Around the same time, ch00beh from SIBR released blaseball-mike, a Python library designed to simplify interfacing with the Blaseball API. And like a little gremlin I rubbed my hands together, threw my existing hacked-together scripts in the bin and threw myself at the new library. The first releases only included the basics: Teams, Players, Games. I sent in pull requests to help expand it to include every corner of the Blaseball API: Election results, Playoff brackets, League Standings, Tiebreakers. Anything we knew about I wanted to help get in there, including an incredibly annoying, manually entered list of every Modification we had seen at the time (which was eventually replaced with an endpoint TGB added but I don't think ever used, but then kept around just for us 🙏).

Old and Busted¶

Pies Oldheads will remember that the original Notes were just Google Docs that I posted in the Pies channels. When making them, I set myself a couple of rules:

  • Never include my opinions. I didn't want this to influence people's decision-making. I did break this rule once or twice, particularly in early seasons.
  • Don't speculate too much. If I don't know what something does then just say I don't know what it does. I would rather be vague than wrong.
  • No spilling secrets. Especially in the early days I had a bunch of information on election items a few days before any of it dropped, and I tried not to let it influence the document. There were a handful of exceptions, and I did share it when possible in Discord chats or in our Election Meetings, but I wanted the Notes to be free from spoilers.

I made the first one for Season 5, then made new ones for every following season until Season 11. Around Season 6 or 7 they somehow ended up being useful to people, so they were pined and reposted at the start of the weekly Election Meeting so people could follow along. The work eventually led to me getting elected as a Pies team Captain (which was renamed to Representative later on) and my work on blaseball-mike got me selected for the SIBR Council of Diviners. Turns out Python is pretty common for data analysis, and a lot of people were using mike for all sorts of projects, even just as a reference for the various API endpoints. Neither of these positions were huge deals, just increasingly smaller group chats, but it felt really nice that these things I spent a few hours working on my spare time were appreciated by people.

New Hotness¶

When the Discipline Era came to an end, I had some time to breath and look back on my process. While the Election Notes as they existed were OK I wanted to make them more useful, easier to read, and (most importantly) easier for me to make. So I set some goals and ground rules:

  • Stick with Python. Not because another language would be better (a bunch of languages would have been way better) but because I already knew it and while I did have some spare time, I didn't have that much spare time.
  • Notes must be static. One of the benefits of the Google Docs based approach is that once a season is over the note persists; a historical artifact of the team at that point in time. I wanted to maintain that as opposed to having the notes auto-pull data from the site. This also had the side effect of not breaking previous Notes as the Blaseball API changed around.
  • Better support for Tables and Graphs. Google Docs is hilariously bad at actually presenting data, so most of the notes on election items were stuck just being a few sentences and maybe an image.
  • Auto-generation of data. Previously, when the league or team changed I had to manually modify the contents of the Google Doc. I had already generated scripts to help automate the analysis portion of this, but nothing translated that to the actual Words on the Page.

Working on blaseball-mike had taught me that "hey people seem to really like Python for the Data Analysis thing" so I looked for existing tools to do what I want. And Jupyter Notebooks ended up being the perfect fit. At least, almost the perfect fit. Original versions of these notes (which an incredibly small amount of Pies might remember when I posted it for feedback) all ran through Binder, an interface that runs the full Jupyter runtime in the browser. While this let anyone do anything (including letting them change things for their own analysis), it also took an incredibly long time to load. Turns out starting a full containerized VM to run a web page every time someone connects is a little slow. My original hope was that by making the code and data available for readers it would let them try things for themselves, but I realized that most of the target audience for this kind of thing wouldn't feel comfortable modifying stuff anyway. Fortunately, the Jupyter Project has a whole tool/library for converting Notebooks to other formats, like HTML. So the workflow ended up looking like this:

  1. Create a new Jupyter Notebook when a new season starts. Early on I did this manually, but I eventually made a script to build the initial file for me.
  2. Add code, comments, and notes for each item on the ballot.
  3. Run the Notebook locally on my computer to fetch the latest data.
  4. Commit & push the Notebook to GitHub.
  5. GitHub Actions will automagically run a script to scan for Notebooks, convert them to HTML, and publish it to GitHub Pages. This script was included in the repository, so I could run it beforehand on my machine to check formatting.

Wrap it all together with some custom Jinja templates for a sidebar and bam: Election Notes. Jupyter Notebooks let me convert in-memory tables into on-page tables, including formatting for heatmaps. About once a day (or after any particularly big in-game event) I would just re-open the Notebook, rerun it, then push the changes. The Notebook itself would automatically pull the latest info, and my code would perform the analysis and spit out whatever info it needed. And boy was it needed.

It's not an exaggeration to say I absolutely would not have been able to keep up with Expansion Era Elections if I hadn't already done all this work ahead of time. Even excluding the new stuff like Wills, the Gift Shop, and Stadium Renovations (which I never included in the notes but I probably could/should have at some point), the rate at which things changed in Expansion Era made the old Google Docs method completely untenable. Once I had gotten all my tooling set up I only ever spent maybe an hour or two a week making the Notes, and maybe a minute or two re-running it every once in a while.

Post-Mortem¶

I'd say overall the Election Notes as they ended up were a success. I pretty regularly got comments from Pies that they were impressed how quickly I could pull them together and how useful they were. They briefly get a mention when the Pies were invited on the Infinite Cities Blaseball Podcast leading to reactions like "What?" and "Does this person need a job?". But most importantly, the notes did their job. I don't think we would have gotten the team to the heights we did without them (even if it didn't lead to a third championship win). They gave the team a reference point so that we could, collectively, rate each of the items on the ballot and decide how to spend our comparatively small amount of votes. The Pies were never a very big team, but we managed to succeed by being smart and agile, similarly to Steaks and The Breath Mints.

There were a few things that I thought could have been improved:

  • I wasn't really using Jupyter Notebooks like you're supposed to. Most data analysis generates a big table with all the data you'd ever need, and then you slice & dice it in order to isolate what you want into the form you need. The way blaseball-mike was set up was that you'd make individual calls for individual items: teams, players, etc. And since I was just re-using mike, my notebooks had the same problem. I fixed this in the refactor I did for Coronation Era, but sadly it didn't get much use.
  • I really wanted some form of interactivity on the site, like sliders or dropdowns to handle situations where Blessings or Wills would hit ranges of stats or players. My choice to stick with Python meant that doing anything dynamic in the browser just never really worked. I ended up having to include analysis for all, or at least some, of the possible outcomes, which lead to some really, really long and unwieldy sections (looking at you, Wills). After Expansion Era ended a project called pyscript came out which would have let me do more, but I never had the time to get the infrastructure for it set up.
  • I probably overused tables in the notes, where it would have made more sense to use graphs or other visualization techniques. The main reason for this is that I never really found a graphing library that I liked. The "industry standard" is matplotlib, which also has hooks into pandas for easier access, but the graphs that spits out are static images which didn't scale well with the Notes format. I ended up going with plotly, which produced nice graphs but was an enormous pain to work with and was pretty poorly documented. There may be some better libraries at this point, I haven't checked. The other reason is I'm bad at analysis and had a hard time figuring out where a graph would make sense vs a table.
  • I think the Notes ended up discouraging other people on the team from doing similar analysis. There's a sense that "if someone is already doing something I shouldn't bother", but I think there's value in having multiple people looking at a problem. Compared to someone doing work in Google Sheets, the Election Notes looked more professional, even when other people's actual analysis would have likely been better than mine.
  • The structure of the notes weren't useful to other teams. Despite being easy for me to use, the infrastructure I built wasn't really usable outside the Pies. Some people might see this as a good thing (our secret sauce), but I kept all the notes and the code to generate it open-source in case people wanted to poke at it. I know glumbarion on the Crabs looked into using it for his notes, and I helped him out a bit with it, but I think he ran into some problems. Ideally the "Generate an HTML Document" part would be different from the "Team-Specific Notes" part, but they were so tightly intertwined it would be hard to separate.

I'm happy for you. Or sorry that happened.¶

Blaseball is a big, weird thing, the memory of which is inseparable from me. There's just so many stories, so many moments, that changed who I am as a person. I learned a whole lot about Python and using it for accessing web-based API endpoints. I helped document those endpoints so they could be used for so many silly and less silly tools to help people enjoy the game. I now have the wording for the "Why do they call it an Oven" meme burned into my memory for the rest of time. I accidentally kick-started the hunt to solve an easter egg in a 25-year-old Salmon Migratory Simulation. I said go pies. A lot.

In the grand scheme of Blaseball, I'm barely a blip on the radar. So many people did so much more than me. But I'm incredibly glad I could help, even a little, at making this experience mean so much to so many people.

Special thanks to:

  • TGB for making an incredible game. I'm only a little upset about all the Rigging it Against the Pies.
  • Ch00beh for letting me help out with blaseball-mike, even though I had no idea what I was doing. Why did I think writing thousands of lines of unit tests was a good idea.
  • SIBR for being, well, SIBR. There's absolutely no group I can think of that's anywhere near as cool, creative, and inclusive as you are in the gaming space. So many people made so many things that will inspire me for the rest of my days.
  • The other Pies Captains for being the backbone of a community that I called home for so long, even when being that backbone was really hard. There were... so many discourses.
  • The Pies Fans for being some of the nicest people I've had the pleasure of spending time with. The previously mentioned discourse was mostly not your fault (mostly 😜).