Mission: Economy - Düsseldorf Hackathon

Over the past weekend I participated in my first ever hackathon here in Dusseldorf. The theme described on the event page was rather vague and didn't really have any clear direction so we weren't sure what exactly to expect. Before arriving we had decided that we wanted to do something interesting and/or fun with the Panama papers data that was released publicly.

Eventually we decided to create a simple website to 'Build Your Own Offshore Corporation', poking fun at the ridiculousness of the companies (if you can even call them that) mentioned in the papers. Using the actual data pulled from the papers we allow the user to generate a name, locate an intermediary to help set up their corporation, and decide which tax jurisdiction to have the company operate in. We used R Shiny to build a quick prototype. It isn't hosted online anywhere but if you clone our github repo you can run it locally.

The funniest part for us was seeing how silly the actual companies names are. A couple of our group member put together the graphic above, using the most common words found in the names. Give it a try to see for yourself!

At the conclusion of the event we ended up taking home the prize for 'Best Pitch'. Which was quite a surprise to us as it seemed that our project was probably not what the judges were really looking for. So all-in-all not a bad way to spend a couple days. It was definitely an interesting experience for my first hackathon.

Finally I'd like to thank everybody in our group that participated! Without them this would not have been quite so successful or fun.

Objective Gametypes and KDA

Something that often gets said regarding objective gametypes (capture the flag, strongholds, etc.) is that KDA (kill-deaths-assists) does not matter as long as you're getting the objectives. So I wanted to dig through some of my recent Halo 5 matches to see if there's any truth to this statement. Using a sample of recent objective games that I completed, a logistic regression was performed using Kills, Assists, and Deaths on the dependent variable of winning or losing. Basically I want to know how much each of these variables influences the probability of winning or losing a game.

This was also a bit of an excuse to play around some more with the language Julia. I've been starting to use it more at work and am really enjoying what it offers. Although it's tough to compete with the whole R ecosystem, thanks to the RCall package it makes the transition pretty painless. Head over to Julia-Lang if you want to know more.

First the non-Julia stuff. Since I want Halo 5 data I'll be using RCall to interface with my R package to get some data. Below is a simple wrapper function to get the match data I want using my h5api package.

using DataFrames, RCall, GLM

api_key = "itsamystery"
slayer_id = "257a305e-4dd3-41f1-9824-dfe7e8bd59e1"

function getRecentMatches(player, modes, start, count, key)
  R"recent_matches <- getRecentMatches(player = $player,
                                          modes = $modes,
                                          start = $start,
                                          count = $count,
                                          key = $key)"
  r_data = R"cbind(rbindlist(lapply(recent_matches$Results$Players, flatten)),
  return rcopy(DataFrame, r_data)

Next, just using a simple loop I'll grab data from 250 of my most recent matches. CLWakaLaka is my gamertag, so you can either use mine again or try your own if you play Halo 5.
match_data = DataFrame()
for i in 0:9
  match_data = [
    getRecentMatches("CLWakaLaka", "arena", i*25, 25, api_key)

This performs a little cleaning up before performing the regression. Besides a win or a lose, it's possible for a match to end in a tie or disconnect. So first only definite win/lose matches are considered. Slayer games are also filtered out. Since kills are the objective in this game type it goes without saying that KDA directly influences your likelihood of winning. Finally the result is changed to a simple 1-0 variable. 1 meaning win and 0 meaning lose.
match_data = match_data[((match_data[:Result] .== 1) | (match_data[:Result] .== 3)) & (match_data[:id] .!= slayer_id), :]
match_data[:Result] = map(match_data[:Result]) do x
  if x == 3
    return 1
    return 0
match_data[:Result] = convert(Array{Float64, 1}, match_data[:Result])

Finally, using the GLM package, a logistic regression is performed in the data with the following results:
my_lm = glm(Result ~ TotalDeaths + TotalAssists + TotalKills,
            Binomial(), LogitLink())

Formula: Result ~ 1 + TotalDeaths + TotalAssists + TotalKills
               Estimate Std.Error   z value Pr(>|z|)
(Intercept)   0.0405304  0.531324 0.0762819   0.9392
TotalDeaths   -0.202424 0.0572149  -3.53796   0.0004
TotalAssists   0.202192 0.0941433   2.14771   0.0317
TotalKills     0.121854  0.049335   2.46993   0.0135

So what does this tell us? Well the logistic function looks like this:
1 / (1 + exp(-( intercept + b1*x1 + b2*x2 + etc. )))
Where bi's are the estimates above and xi's are the data points. For example, if I had a game with 10 kills, 4 assists, and 8 deaths, then my estimated probability of winning that game would be:
1 / (1 + exp(-( 0.0405 -0.202*8 +0.202*4 + 0.122*10 ))) = 0.61 or 61%

From the estimates above: deaths negatively influence the probability of a win and kills and assists influence the probability of a win positively. All three variable estimates have a p-value of less than 0.05 which suggests they are significant factors in the overall outcome of a game (obviously). The intercept, however, is not significant which makes sense since we likely have no data for a 0/0/0 game.

Interestingly, deaths and assists coefficients have roughly equal magnitude while the coefficient for kills is slightly less. This would suggest that the relative importance of these actions corresponds to Deaths = Assists > Kills. Meaning that the most important factors towards getting the win are (in this order): not dying, always shooting/helping teammates, then getting kills.

So there we go, it seems there is a little kernel of truth in the idea that KDA in an objective-based gametype is not everything... Although it certainly helps, and feels so good.