Palaestra Tournaments
Palaestra started at the beginning of my senior year of high school. My math club competition team had the idea to start a club that would do for younger students what these competitions did for us: offer extra motivation to learn beyond the standard course load. As the sole software developer, I was responsible for developing programs to facilitate these competitions for our team.
Palaestra is what I came up with over the span of a month. Unfortunately, my creation never did get the chance to be tested in a live environment: through a combination of factors that I think we all had an inkling of going in, the club never got off the launchpad. The nice thing about developing software, however, is that I still have something to show for my effort!
But what does it do? Well, Palaestra is a web app that hosts tournaments on a local network. I designed it so that we could run the program on one of our host devices, and then the competitors could connect to the server through their web browser and engage in the competition.
We also needed some way to get the tests for those competitions. That is why I also put together an accompanying Java program to, given a JSON template of test questions, generate a unique test in a format that could be imported to Palaestra.
Even though the project was never put into use, I still value what was truly my first chance to dip my toes in the water of not only building apps but also larger-scale projects in general.
What Did It Do?
Let's start with the smaller component: the test generator. It needed to:
- Represent questions as templates that could easily be copied and reworded.
- Store all questions in a separate file for ease of updating.
- Output the resulting test in a format that Palaestra could read and in PDF format for printed tests.
- Randomly generate a test consisting of:
- A random selection of templates.
- Numerical or other values randomly assigned (to ensure unique tests).
- A calculated answer for each question.
Now, this project would have been a lot simpler if not for that last bullet point. I couldn't just have questions and let the answer be decided by a judge: I needed to calculate the answer to an entirely randomly generated question. But more on that later.
Palaestra itself was arguably more critical as the user-facing component. It had to:
- Authenticate facilitators and competitors.
- Allow facilitators to configure a competition's rules and the teams.
- Show a match list and let the facilitator start a match, uploading a test from the test generator.
- Allow competitors to take the test, keeping track of their scores.
- Calculate and display results at the end, both to competitors and on a separate results page.
While I did all that, I would need to also figure out how to build an app that could operate on the web in the first place. Ultimately, since I never intended to use Palaestra outside the context of a LAN-based connection, it made sense to use the programming language I had the most experience in (Java) to deploy a jar file that could easily be run by facilitators who didn't happen to be me.
Laying Down the Bricks
One of the harder parts of building Palaestra came when I needed to handle connections to the competitors. My initial plan was to use a typical web page approach, letting the user press a button when they finished a question to send their answers to the server, which would process whether they got it right or not and return a new page containing the next question.
That was great, except for how the server would be unable to talk to the client on its own. The browser would have to constantly be sending requests to the server for any updates, such as if another competitor has answered the question or if the time has run out. Such a solution would have functioned, but all the unnecessary traffic would have been painful for my soul (not to mention the server having to handle these requests).
The solution? WebSocket connections. In case you aren't aware, WebSocket is a protocol that allows the server to talk back to the client, making bidirectional communication far simpler. With it, the server could simply notify clients whenever an event happens, and then the client-side JavaScript could handle updating the competitor's screen with new information.
As someone entirely new to web development, it was almost like magic. I remember consistently testing the connection both locally on my computer and also across multiple devices, expecting some bit of critical information to get lost somehow on the way back to the client. Yet it worked amazingly well, allowing me to iron out the finer details of how the competition would be facilitated.
Automated Answer Key
But let's take a look at the test generator for a moment. I was building this software to make the life of the facilitator as easy as possible. I didn't want them to have to do much more than apply the chosen configuration options and start matches, so I certainly couldn't force them to answer each question on their own. Yet I needed to know the answer to the questions presented to the competitors so they could be automatically checked and scored.
The solution? My test generator needed to know the answer to any questions it generated. If it could do that, it could store the answer in the data passed over to Palaestra, and then everything would run smoothly without the facilitator having to do any extra work.
Unfortunately, we were inspired by the UIL Calculator Applications competition for our own tests. In that competition, there were a few set types or "templates" of questions that could be asked at every question number. All that would change is the wording and the actual numbers provided. We wanted to do the same.
That meant, however, that I would need to create a method for each question template that would solve it given the randomly generated fields. While I was able to let others help in writing the questions themselves, as the sole developer, I was the only one who could actually implement the solver methods. It grew tedious rather quickly, but I did enjoy the challenge of initially setting up the system.
The thing is, I wanted to be able to reuse solvers for similar questions, kind of like how the Calculator Applications tests could have reworded versions of the same problem. With these stored in a JSON file that I parsed, it made sense to have the file specify the name of the method to call.
Java has a nice little feature that lets me get a reference to every method contained in a class, allowing me to access the method's name and then call it. So I put the solvers in their own class, got a list of every solver, and then checked that list for the solver that a template would specify. This meant that when I randomly generated a question and stored it in its own object, I could also pass it a reference to the method it would need to call to generate the answer. It wasn't groundbreaking, but it felt almost like I was cheating!
Looking Back
I won't deny that I wish this project could be put to use somehow, especially after having put a month of effort into creating it. That might not seem like a long time, but for that month, building this project was my main hobby, my favorite way to spend my free time.
However, I don't regret putting as much effort into it as I did, even if it never got to see the light of day. After all, it was one of the first sizable projects that I ever finished. It was also the web development gateway drug for me: many of my more recent projects would never have happened if not for Palaestra. And as hard as it may be to put a value on fun, this project certainly earned its keep on that metric alone.