notes

Creating a Grade-Based Discord Bot and Trading Game

2021-08-31

At my high school, there was a concept known as "the GPA game." This could refer to a variety of things, but mainly involved improving one's grades or class rank through less than ethical means. However, this post will not be about the drama that surrounded the hypercompetitive academic climate or the stories that came out of it. Instead, this note will be about a parody stock market game I made with some friends to poke fun at the school environment.

Back in sophomore year, I worked with another student to develop an unofficial mobile client for Skyward, the gradebook system our district used. Practically all the actual programming was done by my partner, but I had enough experience with Skyward from a previous project to act in an advisory role. The app was ported across platforms and eventually rewritten in Dart as a Flutter app to keep the experience consistent and save time by minimizing development to a single codebase. In early 2020, the core gradebook scraping code was factored out into an independent module, allowing anyone to use it as a dependency. I should mention that there was no public API (at least that we had access to), and that what was scrapeable was not consistent, nor easy to parse. The first project I created with this library was a small Discord bot that returned the grade details of random assignments. I also added a few competitive commands that compared averages across classes. These interactive "GPA battles" were unexpectedly popular in the servers to which I added the bot. Later on, I also implemented a notification service that sent registered users a message whenever new grades were detected, continuously operating on a thirty minute timer. I had planned to contribute a similar push notification system to my friend's app, but never got around to it.

A Skycord GPA battle comparing two students' averages in seventh-grade math A Skycord GPA battle comparing two students' averages in organic chemistry and third-grade reading

Some battles were fair, and some were not.

A Skycord message showing the results of a US history DBQ A Skycord message showing the results of a physics test

Some grades were reason for joy, and some were not.

Notice the inconsistent formatting and presentation of information. The missing icon in the top-left corner is the user's Discord profile picture. The links to these change when users update their profile pictures, which is why it no longer displays anything. The missing picture on the side would display the student's official school picture, but would disappear a few days later. My assumption is that the authentication for presenting the image was based on a token in the URL that expired after some time, though Discord would keep the image cached for a bit longer. One unrelated tidbit I'd like to add is that it used to be possible to determine the URL of a student's photo if you knew their student ID, as that was the only parameter in the URL. Unfortunately (fortunately?), this was patched after I entered high school, so I was never able to take advantage of it besides building a small proof-of-concept program.

After a month or so, the Discord bot was getting old. Sure, the notifications were useful, but you can only pull up random grades for so long before it becomes boring. I asked around for ideas on what I could add to make the bot more engaging: perhaps more gameified features or commands that did bigger things? This is where I got the suggestion to make a stock market game based around grades. An excerpt of the conversation is copied below, with names removed and some portions redacted for privacy.

2020.03.26 - 12:13 PM CDT
<suggester> do a stock market on ppl grades
<me> uh
<me> A what [custom emoji expressing great laughter]
<me> This sounds interesting
<suggester> ppl can buy shares in a person
<suggester> if their grades are going to increase
... [discussion of hypothetical strategies]
<me> This sounds so ******** and [school name]like I love it
<suggester> yay
<suggester> happy to help
<me> Actually having to implement it though [custom emoji expressing unease]
<me> [custom emoji expressing anxiety and fear]
<suggester> oh do u want an easier idea
<suggester> not that i have one
<partner> wait
<partner> thats such a good idea
<partner> wtf
<suggester> yes
... [discussion of specific implementation details]
<me> Bro at this point we gotta make this more than just a Discord command
<me> I wanna create a proper website and **** for this
<partner> lmao
<partner> thatd be fun
<partner> ngl
<me> Yea
<me> Very fun

At the start of senior year, my new partner and I began work on "The GPA Game." Note that my partner here was not the app developer I worked with previously, although he did help with troubleshooting problems related to the Skyward library. As I possess very poor web design skills (evident from this site) and had experience with the library, I worked on the backend system while my partner worked on the frontend web app. The server kept track of investments in a database and updated records according to the entry of new grades, drawing upon my experience building the grade notification feature for the Discord bot. One of the biggest challenges involved in this was how messily Skyward presents grades. Figuring out which assignments were old, which were new, and which had their scores updated was tough. Another unexpected hurdle was working around the issues in the server framework I chose. I figured it made the most sense to develop the server in the same language as the library for easy integration, but this proved to be a mistake. The biggest server library I found for Dart was riddled with bugs and general issues that made development painful. I ended up spending far more time working around my tools than working on the program itself. It came as a bummer, but not a surprise, when the framework was deprecated while I was halfway through development. Ah well, I had already put so much time and effort into the program; I couldn't imagine starting over again. In spite of all this, we were able to work through most issues and eventually released a pretty functional game.

The signup form accepting user credentials The signup flow scraping a new user's Skyward account

TODO: Add more pictures after blurring out names

We launched the game and shared it with our friends, fixing bugs and tweaking things as we went along. I planned to promote the game to a wider audience after polishing it some more, but eventually decided against doing so. It's unlikely that the school administrators would have been pleased to discover I was essentially collecting school account information from dozens, if not hundreds of students had I gone through with a public launch. We only ended up playing around with the game for a few days, but still felt pretty satisfied with what we had created. The GPA Game wasn't fun (much like the real thing) and probably violated every game design guideline out there. It was the act of bringing a crazy idea to life, and knowing the effort that went into it firsthand, that made seeing the final product so rewarding.