Development

How we designed, built, and ran our first community Hackathon

January 16, 2025
How we designed, built, and ran our first community Hackathon

In Sep­tem­ber, we held Michi­gan Soft­ware Labs’ first Hackathon! We invit­ed col­lege stu­dents and peo­ple new to their soft­ware devel­op­ment career to par­tic­i­pate and work togeth­er in teams on a prob­lem. We planned this Hackathon through­out the year, and the event was a blast to exe­cute. This arti­cle is intend­ed to ful­fill our com­mit­ment to the par­tic­i­pants and the devel­op­er com­mu­ni­ty by shar­ing our process for plan­ning the event under var­i­ous con­straints — and a por­tion of the source code.

Plan­ning process #

We start­ed work at the begin­ning of the year with a sin­gle goal: run­ning a Hackathon. We invit­ed any Michi­gan­Labs team mem­bers inter­est­ed in vol­un­teer­ing their time to join our group and take part in this effort. We then began with a clear pur­pose: A fun, approach­able prob­lem that a team can solve in one day.

We knew that the event had to fit into a sin­gle day, and it had to be inter­est­ing enough to work on. So we start­ed brain­storm­ing ideas and prob­lem sets. We looked at oth­er hackathons that have been offered to col­lege stu­dents, explor­ing what made them successful.

We land­ed on a rat maze prob­lem, where par­tic­i­pants would con­trol their own rat” and nav­i­gate it through var­i­ous mazes blind. We had a cou­ple, sim­ple tech­ni­cal goals in mind to keep the prob­lem accessible:

  • The participant’s code needs to be plat­form agnostic
  • The par­tic­i­pant must inter­act with the maze through REST APIs
  • Clear, objec­tive scor­ing with min­i­mal chance for ties

But the rat maze prob­lem itself isn’t unique, so we need­ed to add a spin on it — which was option­al” goals for par­tic­i­pants. We land­ed on backtracking.

By adding cheese through­out each maze, the rats had the abil­i­ty to smell” where near­by cheese might be. Eat­ing the cheese increased the score a lit­tle, but bring­ing the cheese to the end of the maze one-by-one was worth a lot more. This made the par­tic­i­pants’ objec­tives the following:

  1. Fin­ish­ing the maze is worth the most points
  2. Fer­ry­ing cheese to the end of the maze is worth a good amount of points
  3. Eat­ing cheese along the way is worth a small amount of points

When con­sid­er­ing these objec­tives, we want­ed to rule out a cou­ple easy approach­es. One being brute-force, where it would be pos­si­ble to find all cheese and the end of the maze giv­en enough time. So we imple­ment­ed score penalties:

  1. Mov­ing the rat reduced the teams’ score by a lit­tle, incen­tiviz­ing smarter back­track­ing and navigation
  2. Sniff­ing” for cheese reduced the score by a lit­tle, incen­tiviz­ing more intel­li­gent rout­ing to locate cheese
  3. If the rat nev­er reached the end of a maze, they wouldn’t get any points, incen­tiviz­ing find­ing the end as the pri­ma­ry goal for every­one, and mak­ing cheese more of a side objective
  4. There was a max­i­mum amount of API calls a team would make per maze, adding resource scarcity

At first, every­thing seemed fine, but some­thing was miss­ing: the fun fac­tor we want­ed to empha­size. Visu­al­iz­ing the maze one move at a time made it hard to get a com­plete pic­ture, and trou­bleshoot­ing how well the algo­rithm was per­form­ing could be chal­leng­ing, espe­cial­ly for visu­al thinkers.

We added a cou­ple new features:

  • We would pro­vide a visu­al trou­bleshoot­ing tool so that par­tic­i­pants could run their rats through sam­ple mazes while they devel­op their algorithm
  • We would pro­vide a swag­ger page for our API to help peo­ple who were new to REST calls
  • We would sim­u­late all of the teams run­ning through each maze in the grand finale, using Unity3D

To bring our Hackathon to life, we need­ed to cre­ate sev­er­al components:

  • A back­end to serve as the main API infrastructure
  • A fron­tend trou­bleshoot­ing tool to visu­al­ly test mazes (com­pe­ti­tion mazes remained hidden)
  • The mazes themselves
  • A Unity3D simulator
  • Load test­ing tools
  • Beta test­ing processes
  • A hackathon sched­ule, includ­ing the agen­da, cater­ing, prizes, and swag

While this list might have seemed daunt­ing at first, care­ful plan­ning and del­e­ga­tion made it manageable.

We tack­led it in our spare time, using Jira to track the over­all effort. Treat­ing this like a bill­able project, we tracked hours, allo­cat­ed time thought­ful­ly, and main­tained dili­gence with our esti­mates to stay on schedule.

Below is a screen­shot of our Jira board mid-project, show­ing the ener­gy and activ­i­ty invest­ed across mul­ti­ple areas: 

screenshot of project management software

The Back­end #

Github Repo Link

As with all aspects of the project, we aimed to make this a valu­able learn­ing expe­ri­ence for our team.

For the back­end, we chose ExpressJS, which gave us an oppor­tu­ni­ty to deep­en our knowl­edge of the plat­form. We dis­cov­ered inno­v­a­tive ways to set up authen­ti­ca­tion and mid­dle­ware, imple­ment­ed rate lim­it­ing, con­duct­ed load test­ing, and effec­tive­ly man­aged API keys. One fea­ture that stood out was the auto­mat­ic Swag­ger doc­u­men­ta­tion the team suc­cess­ful­ly imple­ment­ed. This was an impres­sive addi­tion, mak­ing it easy for any­one to explore and under­stand the capa­bil­i­ties of the new API.

David stands in front of large TVs giving a presentation showing the REST API documentation

The Fron­tend #

GitHub repo link

Our fron­tend test­ing web­site was built using Nex­tJS and React. The goal was to cre­ate it as effi­cient­ly as pos­si­ble while pro­vid­ing max­i­mum val­ue for par­tic­i­pants. The web­site allowed users to enter their API key and view the test mazes, track their moves, and reset their rat as needed.

Par­tic­i­pants had unlim­it­ed access to test mazes through­out the day, but the com­pe­ti­tion mazes were locked until lat­er and couldn’t be viewed through the web­site tool. The web­site also dou­bled as an admin dash­board for us, so we could eas­i­ly keep track of par­tic­i­pants and their progress through­out the day.

short video of the admin dashboard

Mazes #

Because we didn’t have unlim­it­ed time to work on this project, we want­ed maze gen­er­a­tion to be easy, visu­al, and imme­di­ate­ly usable. We chose Google Sheets and used a clever Apps Script, where we could enter a piece of cheese, and it would auto­mat­i­cal­ly place smell” val­ues in a radius around the cheese. This let us review maze designs col­lab­o­ra­tive­ly, with­out hav­ing to devel­op a tool to do it.

short video of the maze

The source code of our action script:

function onEdit(e) {
  var range = e.range;
  var sheet = range.getSheet();
  var startValue = range.getValue();
  console.log(`Start Value: "${startValue}"`)
  console.log(`Old Value ${e.oldValue}`)
  if (startValue != "C" && e.oldValue != "C") {
    return;
  }
  var writeValues = startValue == "C";
  var startRow = range.getRow();
  var startCol = range.getColumn();
  var maxDistance = 5;
  var queue = [[startRow, startCol, 0]];
  var visited = new Set();
  visited.add(`${startRow},${startCol}`);
  console.log("Starting loop.");
  while (queue.length > 0) {
    var [row, col, distance] = queue.shift();
    console.log("Acting on queue...")
    if (distance <= maxDistance) {
      console.log("Distance is in range...")
      if (distance > 0){
        if (writeValues) {
          // Write to sheet
      sheet.getRange(row, col).setValue(distance);
        } else if (sheet.getRange(row, col).getValue() == distance) {
          sheet.getRange(row, col).setValue("");
        }
      }
      var neighbors = [
        [row - 1, col], // up
        [row + 1, col], // down
        [row, col - 1], // left
        [row, col + 1], // right
      ];
      for (var i = 0; i < neighbors.length; i++) {
        var [newRow, newCol] = neighbors[i];
        console.log(`Iterating over the neighbor ${newRow}, ${newCol}`);
        if (newRow > 0 && newCol > 0 && newRow <= sheet.getMaxRows() && newCol <= sheet.getMaxColumns() && !visited.has(`${newRow},${newCol}`)) {
          var neighborValue = sheet.getRange(newRow, newCol).getValue();
          if(!isNaN(neighborValue) || neighborValue === "") {
            console.log(`Adding ${newRow}, $`)
            queue.push([newRow, newCol, distance + 1]);
            visited.add(`${newRow},${newCol}`);
          }
        }
      }
    }
  }
}

When­ev­er we made an update to the spread­sheet, we could run a com­mand on the back­end to pull the cell data and regen­er­ate the table in our Post­greSQL database.

Unity3D sim­u­la­tion #

Unity3D Sim­u­la­tion

We had a cou­ple team mem­bers with expe­ri­ence in Uni­ty, and we want­ed to use their skills to make some­thing fun for the grand finale. We chose to keep track of every sin­gle move a rat makes. Then the sim­u­la­tion would play” the moves back, so we could watch all the teams togeth­er on the big screen.

watching maze animation on a large TV

This was a great learn­ing expe­ri­ence for our team mem­bers who were new to Uni­ty, as they learned a lot about Can­vas UI, ani­ma­tions, LOD, and gen­er­al game design prin­ci­ples. The sim­u­la­tion would stag­ger the par­tic­i­pants, since each team was iso­lat­ed to their own maze and there was no resource scarci­ty, and reveal their score at the end. We could con­trol the sim­u­la­tion speed and select mazes and start/​pause if we need­ed. This was eas­i­ly one of the high­lights of the day, where teams were able to see their rat’s per­for­mance live!

video of maze navigation in-progress

A close­up of some of the animations:

video of a closeup of Unity3D animations of the mouse navigating the maze

One thing to note is that while we’re shar­ing the source code of this Uni­ty project, there are some third par­ty assets we can’t share due to licens­ing. But the basics are there.

Load test­ing #

We used Artillery to load test our back­end, to make sure that it could han­dle rate lim­it­ing and a large num­ber of par­tic­i­pants. Here’s an exam­ple artillery script that would run through a cou­ple move­ments and reset the rat repeatedly:

config:
  target: "http://localhost:8080/v1"
  phases:
    - duration: 1
      arrivalRate: 1
  defaults:
    headers:
      Content-Type: "application/json"
      X-API-KEY: "<API-KEY>"

scenarios:
  - name: "Rat reset"
    flow:
      - post:
          url: "/rat/reset"
          json:
            mazeId: "oneTurn"
      - post:
          url: "/rat/smell"
          json:
            mazeId: "oneTurn"
      - post:
          url: "/rat/move"
          json:
            mazeId: "oneTurn"
            direction: "NORTH"
      - post:
          url: "/rat/move"
          json:
            mazeId: "oneTurn"
            direction: "NORTH"
      - post:
          url: "/rat/eat"
          json:
            mazeId: "oneTurn"

Beta test­ing #

It’s easy to get biased results when the same team that cre­ates the project is also solv­ing it. To address this, we involved peo­ple across our com­pa­ny with vary­ing lev­els of soft­ware devel­op­ment expe­ri­ence. A cou­ple of our devel­op­ers tack­led the prob­lem, and we paired them with non-tech­ni­cal employ­ees to work through it togeth­er. This approach solved two key challenges:

  1. We need­ed more entry-lev­el attempts at solv­ing the problem.
  2. We’re always look­ing for ways to help non-tech­ni­cal team mem­bers at Michi­gan­Labs gain deep­er insight into the soft­ware devel­op­ment process.

The beta test­ing proved to be high­ly suc­cess­ful. Team mem­bers from deliv­ery leads, busi­ness oper­a­tions, and even our exec­u­tive assis­tant par­tic­i­pat­ed in the chal­lenge — help­ing us iden­ti­fy issues with doc­u­men­ta­tion and oth­er poten­tial prob­lems. This process pro­vid­ed valu­able user feed­back and ensured that the event was well-val­i­dat­ed by a diverse range of exper­tise before going live.

person standing in fron of large TV pointing at the maze simulation

The agen­da #

We care­ful­ly planned the entire day, set­ting hard stops and clear tim­ings for each phase to keep every­thing on track. To make the event even more mem­o­rable, one of our design­ers cre­at­ed a cus­tom t‑shirt logo for the event, which turned out great and added a nice touch to the swag.

a MichiganLabs team member works with two student participating in the Hack-a-thon

We also gave out tro­phies to our win­ners, which were 3D print­ed. The win­ning team — Adam Byle and Nick Roberts from Calvin Uni­ver­si­ty — each received $200, and the sec­ond place team got $50 each.

the winners of the MichiganLabs Hack-a-thon

Adam and Nick from the win­ning team also open-sourced their solu­tion to our prob­lem, which you can check out here

Par­tic­i­pants spent the entire day with us, col­lab­o­rat­ing with our team mem­bers to work through the prob­lem set. A big thank you to all the par­tic­i­pants for ded­i­cat­ing your time, and to the Michi­gan­Labs team for vol­un­teer­ing your exper­tise to make this event a success!

We learned so much about run­ning com­mu­ni­ty events and thor­ough­ly enjoyed the process of design­ing and host­ing the chal­lenge. As promised, here is the open-sourced code:

Thank you also to Madi­son Cole­man, our stu­dent photographer!

David Crawford
David Crawford
Software Developer

Looking for more like this?

Sign up for our monthly newsletter to receive helpful articles, case studies, and stories from our team.

When to “shape up” versus be more “agile”
Business Process

When to “shape up” versus be more “agile”

May 30, 2024

Should you develop your new software using the Agile or Shape Up method? Here’s how to decide.

Read more
The Pareto Principle at work in software
Business Process

The Pareto Principle at work in software

December 4, 2023

Read more
Innovation in healthcare
Business Development

Innovation in healthcare

December 16, 2024

Healthcare innovation is transforming patient care and productivity. From voice-to-text tools that save doctors' time to groundbreaking gene therapy restoring hearing, these advancements enhance efficiency while focusing on life-changing outcomes.

Read more
View more articles