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"
R"library(h5api);library(data.table)"
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)),
id=recent_matches$Results$GameBaseVariantId)"
return rcopy(DataFrame, r_data)
end
```

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 = [
match_data;
getRecentMatches("CLWakaLaka", "arena", i*25, 25, api_key)
]
end
```

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
else
return 0
end
end
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,
match_data,
Binomial(), LogitLink())
Formula: Result ~ 1 + TotalDeaths + TotalAssists + TotalKills
Coefficients:
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

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

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.