A few weeks ago, Taser contacted me about calculating the avoidance diminishing returns coefficients for monks to greater accuracy. As you might remember, we managed to do this for paladins a little less than a year ago by using an addon called Statslog. Prior to that post, we had already determined coefficients for Paladins, Druids and Brewmaster Monks, but via a less rigorous data collection method (the character sheet) that gave less accurate estimates of the true value of these constants.
For example, we were able to peg the k-factor for monks at $k=1.422$, but the dodge and parry caps had a much wider range of possible values. The best we could do for those were:
$C_p = 91 \pm 7$
$C_d = 505 \pm 25$
That’s not super-accurate, and while they give reasonable enough results, it’s always nice to have better accuracy. We’re also aided by the fact that we now know the exact conversion rates of strength to parry and agility to dodge for all five tanking classes, which eliminates some unknowns.
I asked Taser to collect a data set for me using Statslog so that I could perform a more accurate analysis on monks, and he graciously agreed. After calculating the results and updating Simcraft, I realized that we may as well cover the other three tanks, so I collected data sets for druids, death knights, and warriors.
I also spent some time updating my methods for performing these fits. In the past, calculating these fits generally meant spending a bunch of time in MATLAB hand-arranging the data and then working with the curve fitting toolbox GUI. It also means that every time I sit down and do these calculations, I end up with slightly different methods. Thus, I had a folder full of MATLAB files from different months, all doing the same thing in slightly different ways.
I decided it was time to streamline, so I cleaned up all of that mess and built an efficient system that I can use for all five classes. Now all I need to do is change the text file containing the data, and the various functions I’ve written to parse, arrange, and fit the data do all the hard work for me.
This is Taser’s data, which was rather extensive. He was very clever and used the Steadfast Talisman of the Shado-Pan Assault to achieve incredible coverage of the dodge surface, which led to an excellent fit. Below are the plots, followed by the fitting data. After the goodness-of-fit information, I’ve given the values for $C$ and $k$ to roughly the accuracy that the fit allows.
##### Dodge Fit ##### General model: dfit(x,y) = 3+111/951.158596+(x/951.158596+y)/((x/951.158596+y)/C+k) Coefficients (with 95% confidence bounds): C = 501.3 (501.3, 501.3) k = 1.422 (1.422, 1.422) sse: 1.0609e-010 rsquare: 1.0000 dfe: 151 adjrsquare: 1.0000 rmse: 8.3822e-007 C = 501.25348 +/- 0.00032 k = 1.422000108 +/- 0.000000038
##### Parry Fit ##### General model: pfit(x,y) = 8+95/10000.000000+(x/10000.000000+y)/((x/10000.000000+y)/C+k) Coefficients (with 95% confidence bounds): C = 90.64 (90.64, 90.64) k = 1.422 (1.422, 1.422) sse: 4.0761e-011 rsquare: 1.0000 dfe: 151 adjrsquare: 1.0000 rmse: 5.1956e-007 C = 90.64244 +/- 0.00014 k = 1.42200013 +/- 0.00000018
As you can see, this method does a LOT better. We’ve confirmed our $k$ value to more decimal places and have narrowed down the range on $C_p$ and $C_d$ to almost 4 decimal places.
To summarize the results:
$k = 1.422000(13) \pm 0.00000018$
$C_d = 501.253(48) \pm 0.00032$
$C_p =90.642(44) \pm 0.00014$
Monks also get 1% parry from 10000 strength and 1% dodge from 951.158596 agility.
This is data that I collected using a pre-made character on the PTR. Thus, I didn’t have access to the valor trinket, but I made up for it by using the free T16 gear (thanks Flaskataur!) and trying lots of reforge and gemming configurations to try and cover as much of the surface as possible. We also don’t need to worry about parry for the druids, since that’s identically zero.
This time I’ll link the residuals plots, but not show them explicitly.
##### Dodge Fit ##### General model: dfit(x,y) = 5+99/951.158596+(x/951.158596+y)/((x/951.158596+y)/C+k) Coefficients (with 95% confidence bounds): C = 150.4 (150.4, 150.4) k = 1.222 (1.222, 1.222) dgof = sse: 6.4926e-011 rsquare: 1.0000 dfe: 115 adjrsquare: 1.0000 rmse: 7.5138e-007 C = 150.375938 +/- 0.000041 k = 1.222000009 +/- 0.000000045
Again, this gives a better confidence interval than our previous attempt. Last time, we were only certain of the dodge cap to $\pm 0.2$. This time, we’re accurate to $\pm 0.000041$. To summarize
$k = 1.2220000(09) \pm 0.000000045$
$C_d =150.3759(38) \pm 0.000041$
Druids also get 1% dodge from 951.158596 agility, and obviously gain no parry from strength.
Again, this is my own data set, using a pre-made character and buying all of the T16 gear. This time I used both DPS and Tanking sets to try and get wider coverage of both surfaces.
##### Dodge Fit ##### General model: dfit(x,y) = 5+131/10000.000000+(x/10000.000000+y)/((x/10000.000000+y)/C+k) Coefficients (with 95% confidence bounds): C = 90.64 (90.64, 90.64) k = 0.956 (0.956, 0.956) dgof = sse: 9.8586e-012 rsquare: 1.0000 dfe: 129 adjrsquare: 1.0000 rmse: 2.7645e-007 C = 90.642574 +/- 0.000010 k = 0.956000090 +/- 0.000000018
##### Parry Fit ##### General model: pfit(x,y) = 3+209/951.158596+(x/951.158596+y)/((x/951.158596+y)/C+k) Coefficients (with 95% confidence bounds): C = 237.2 (237.2, 237.2) k = 0.956 (0.956, 0.956) pgof = sse: 1.9542e-010 rsquare: 1.0000 dfe: 129 adjrsquare: 1.0000 rmse: 1.2308e-006 C = 237.18614 +/- 0.00015 k = 0.956000019 +/- 0.000000055
Again, excellent accuracy. Here’s the summary:
$k = 0.9560000(90) \pm 0.000000018$
$C_d = 90.6425(74) \pm 0.000010$
$C_p = 237.186(14) +/- 0.00015$
I could probably improve the parry fit a little by grabbing more points in the high-parry-rating, low-strength region, but this is good enough to give exact character sheet results.
Death Knights also get 1% parry from 951.158596 strength and 1% dodge from 10000 agility.
Warriors took the longest because there’s block to consider. So I had to gem/gear for strength, then convert to dodge, then parry, then mastery. And then write another fitting function for the block fit. However, I’m quite pleased with the results.
##### Dodge Fit ##### General model: dfit(x,y) = 5+133/10000.000000+(x/10000.000000+y)/((x/10000.000000+y)/C+k) Coefficients (with 95% confidence bounds): C = 90.64 (90.64, 90.64) k = 0.956 (0.956, 0.956) dgof = sse: 8.2286e-012 rsquare: 1.0000 dfe: 164 adjrsquare: 1.0000 rmse: 2.2400e-007 C = 90.6425465 +/- 0.0000052 k = 0.956000078 +/- 0.000000011
##### Parry Fit ##### General model: pfit(x,y) = 3+206/951.158596+(x/951.158596+y)/((x/951.158596+y)/C+k) Coefficients (with 95% confidence bounds): C = 237.2 (237.2, 237.2) k = 0.956 (0.956, 0.956) pgof = sse: 7.6114e-011 rsquare: 1.0000 dfe: 164 adjrsquare: 1.0000 rmse: 6.8126e-007 C = 237.186091 +/- 0.000057 k = 0.956000014 +/- 0.000000022
##### Block Fit ##### Warning: Ignoring extra legend entries. > In legend at 294 In blockFit at 58 In warrior at 28 pfit = General model: pfit(x) = 13+1/(1/C+k/round(128*x)*128) Coefficients (with 95% confidence bounds): C = 150.4 (150.4, 150.4) k = 0.956 (0.956, 0.956) pgof = sse: 9.6280e-011 rsquare: 1.0000 dfe: 164 adjrsquare: 1.0000 rmse: 7.6621e-007 C = 150.37568 +/- 0.00015 k = 0.955999849 +/- 0.000000067
The block fit was sort of irritating, because I found out during data processing that the game doesn’t re-calculate block immediately. I had some data points where I had exactly the same mastery but different block values. After looking at the timestamps and the stat changes, it was clear that this is just a reporting error on the game’s part. For example, I’d find two time-adjacent data points that had different mastery rating values but identical block chances. The next data point has the same mastery rating value as the previous one, but the block chance had finally updated.
It’s curious because I didn’t see this effect with any of the other stats – dodge and parry always updated immediately. It may be that block is calculated less frequently, or done server-side, or some other oddity. I’m not really sure. I ended up omitting these obviously-errant data points before performing the fit. They were easy to find, since they were all extremely far off of the curve created by the rest of the points.
So, to summarize for Warriors:
$k = 0.9560000(78) \pm 0.000000011$
$C_d = 90.64254(65) \pm 0.0000052$
$C_p=237.1860(91) \pm 0.000057$
$C_b =150.375(68) \pm 0.00015$
Warriors also get 1% parry from 951.158596 strength and 1% dodge from 10000 agility.
Summary Table For All Classes
Since it might be convenient to have everything in one place, here’s a table listing the different coefficients for each class. The paladin data is from last year’s post.
Since it’s pretty clear that the $k$ values are nearly exact to three digits, I’m going to make the assumption that they are, as it has no significant effect on the results.
|Death Knight||$0.956$||$90.6425(74) \pm 0.000010$||$237.186(14) \pm 0.00015$||-|
|Druid||$1.222$||$150.3759(38) \pm 0.000041$||-||-|
|Monk||$1.422$||$501.253(48) \pm 0.00032$||$90.642(44) \pm 0.00014$||-|
|Paladin||$0.886$||$66.56744(62) \pm 0.0000060$||$237.1860(40)\pm 0.000055$||$150.3759(469)\pm 0.0000094$|
|Warrior||$0.956$||$90.64254(65) \pm 0.0000052$||$237.1860(91) \pm 0.000057$||$150.375(68) \pm 0.00015$|
In this arrangement, it’s easy to see that the plate tanks all share the same parry cap $C_p$. Death Knights and warriors have the same dodge cap $C_d$ and $k$ value, but paladins differ slightly in both departments. The block cap $C_b$ is the same for both blocking classes. Druids and monks both do their own thing, though the monk parry cap is identical to the warrior/DK dodge cap.
Here’s a second table listing the strength-to-parry and dodge-to-agility conversions for each class. This is sort of obvious, since you get 1% avoidance from 951.158596 of your primary stat, and 1% avoidance from 10000 of your non-primary stat, but I’m including it for completeness.