MMO News and theorycrafting for advanced MMO gamers. News and articles that relate to your gameplay. World of Warcraft, SWTOR, Guild Wars 2, Rift, TERA, Eve Online, Star Wars the Old Republic, Diablo3, The Secret World and all Western AAA MMOs

Hello There, Guest! Register

 DPS Excel calculator for Sorcerer / Sage
01-08-2012, 04:42 AM
Post: #11
 lostdummy Respected Member Posts: 100 Joined: Nov 2011 Reputation: 1
RE: DPS Excel calculator for SI Sorcerer
(01-08-2012 04:34 AM)Kor Wrote:  I modified my old Harnessed Darkness simulator to check on Conduction stacks, and it apparently is a very chaotic system. The program itself lets you specify a range of casting intervals, plus a step interval along that range (range must be evenly divisible by the step interval). It will output the results to a file for easy access.

I ran the simulation at 100000 iterations per step, from a cast interval of 1.5 seconds (spammed) to 9 seconds, and I ran that same simulation 5 times, averaging the results. Here are the results for average number of stacks at each interval:

Nice, this probably save me from writing my own simulation ;p

But can you post average values for lower frequencies than 9sec (for example once in 15, 20, 25 and 30sec)?

It would be good to have those few additional data points until 30sec - since after 30sec it is simple to calculate. Then I can plug those points into interpolation table I already use in excel - right now I just filled that with some guesstimated data.
01-08-2012, 05:20 AM (This post was last modified: 01-08-2012 05:29 AM by Kaedis.)
Post: #12
 Kaedis Posting Freak Posts: 1,587 Joined: Sep 2011 Reputation: 7
RE: DPS Excel calculator for SI Sorcerer
30 is simple, it can never refresh the buff, so it has a 30% chance of 30 seconds of buff each duration, so 30% uptime at 1 stack, 0.3 stacks average.

here's 10-25 in 5 second steps:

Code:
```Intv  Average     Iterations---------------------------------------------- 10    0.653638    0.676758    0.841029    0.583018    0.924142    0.243242 15    0.698535    0.798290    0.698723    0.744937    0.616169    0.634558 20    0.654924    0.981560    0.402000    1.022820    0.298138    0.570102 25    0.401180    0.337051    0.332634    0.306882    0.579488    0.449847```

Side note, and I probably should have included this in my original post. My sim uses a random cast system as well as a random proc chance. In other words, if you tell it to cast at an interval of 5 seconds, it doesn't cast every 5 seconds. Instead, every step (0.5 seconds default), it gives you a step/interval (in this case, 10%) chance of starting a cast at that time. This is to simulate the fact that LS doesn't get cast precisely at those intervals, and to simulate periods of higher or lower LS casting due to fight mechanics and such. The variability of the results of the simulation would probably be cut down significantly if I used a static casting interval instead, and I may go back and alter the program to do so and post the results with that if I have time in the next few hours.

Edit: actually, going to do that, since I believe my math on that was wrong anyway. My 1.5 interval set actually only has a 0.333% chance each step to cast, when it should have a 100% chance (since it skips the steps during the cast).

Even Angels must kill from time to time...
01-08-2012, 09:11 AM
Post: #13
 Kaedis Posting Freak Posts: 1,587 Joined: Sep 2011 Reputation: 7
RE: DPS Excel calculator for SI Sorcerer
Here's the updated data with the rebuilt simulator (code below). Sim now casts every seconds, rather than randomly at a chance designed to meet that interval. Slightly less accurate representation of reality, significantly less chaotic and thus more reliable results:

Code:
```Intv   Average     StDev       Iterations                 1.5    2.911478    0.027258    2.91919    2.87551    2.92025    2.94722    2.89522 3.0    2.599370    0.202097    2.81081    2.30539    2.76660    2.57559    2.53846 4.5    2.251296    0.368155    2.60544    1.74872    2.61722    2.20000    2.08510 6.0    1.808940    0.469897    2.36090    1.46014    2.19643    1.77082    1.25641 7.5    1.412733    0.609129    1.97436    1.91999    1.58461    0.55557    1.02913 9      1.283724    0.612461    1.79321    1.94203    1.33962    0.50505    0.83871 10     1.133451    0.203444    1.05140    1.01996    0.90512    1.38999    1.30078 15     0.648147    0.242290    0.45863    0.51774    0.55096    0.65000    1.06341 20     0.545223    0.245237    0.24324    0.75000    0.36384    0.55085    0.81818 25     0.466578    0.213076    0.21908    0.49130    0.37778    0.44444    0.80029 30     0.232993    0.166307    0.16667    0.37500    0.14286    0.04294    0.43750```

Updated code:

Code:
```// PROVIDED BY: Kor // CONTACT E-MAIL: [redacted] // FILE: conduction_simulator.cxx // VERSION: 1.0.3.r // PURPOSE: Simulate the SI Sorc talent Conduction for the MMO SW:TOR // DIRECTIVES ----------------------------------------------------------------- #include <cstdlib> #include <iostream> #include <fstream> #include <cstring> #include <cmath> #include <cassert> #include <ctime> using namespace std; // ---------------------------------------------------------------------------- // GLOBAL CONSTANTS ----------------------------------------------------------- const size_t MINLENGTH = 180;    // Minimum iteration length in seconds const size_t MAXLENGTH = 300;    // Maximum iteration length in seconds const size_t MAXSTACKS = 3;        // Maximum stack size const double CHANCE = 0.3;        // Chance of proc const double DURATION = 30;        // Duration of proc const double MIN = 1.5; const double MAX = 30; // ---------------------------------------------------------------------------- // MODELS --------------------------------------------------------------------- // Holds all information for a single simulation iteration.  Also used for // minimum, maximum, and average struct iteration {     double duration;                // Duration in seconds of the iteration     double stacks[MAXSTACKS + 1];    // Duration in seconds at each stack count }; // ---------------------------------------------------------------------------- // FUNCTION PROTOTYPES -------------------------------------------------------- iteration sim(size_t duration, double interval); // ---------------------------------------------------------------------------- // ============================================================================ int main() {     ofstream file;          // Clear file before writing to it     file.open ("conduction_sim_output.txt");     file.close();          file.open ("conduction_sim_output.txt", ios::out | ios::app);     size_t numits;     double minspread;     double maxspread;     double interval;     size_t duration;     double avg = 0;          // Request number of iterations     cout << "Number of iterations? ";     cin >> numits;          if(numits <= 0)     {         cout << "Can't have zero iterations!" << endl;         exit(0);     }              // Request minspread     cout << "Minimum spread in seconds? ";     cin >> minspread;          if(minspread < MIN)     {         cout << "Minimum spread too small!" << endl;         exit(0);     }          // Request maxspread     cout << "Maximum spread in seconds? ";     cin >> maxspread;          if(maxspread > MAX)     {         cout << "Max spread too large!" << endl;         exit(0);     }          // Request maxspread     cout << "Spread interval? ";     cin >> interval;     if(interval > 0 && (maxspread-minspread)/interval != floor((maxspread-minspread)/interval))     {         cout << "Interval not even divisor of spread range." << endl;         exit(0);     }          size_t steps = int((maxspread-minspread)/interval + 1);          iteration average[steps], min[steps], max[steps], its;          // Repeat test as necessary for interval     for(size_t j = 0; j < steps; ++j)     {         // Run simulation specified number of times         for(size_t c = 0; c < numits; c++)         {             // Generate a random duration between the minimum and maximum (inclusive)             duration = MINLENGTH + (rand()%(MAXLENGTH - MINLENGTH + 1));                          its = sim(duration, minspread + j*interval);                          if(!c)             { // Initialize on first run                 min[j].duration = its.duration;                 max[j].duration = its.duration;                 average[j].duration = its.duration;                 for(size_t k = 0; k <= MAXSTACKS; ++k)                 {                     min[j].stacks[k] = its.stacks[k];                     max[j].stacks[k] = its.stacks[k];                     average[j].stacks[k] = its.stacks[k];                 }             }             else             { // Track Min, Max, and Average                 if(its.duration < min[j].duration)                     min[j].duration = its.duration;                      if(its.duration > max[j].duration)                     max[j].duration = its.duration;                 average[j].duration = ((average[j].duration * c) + its.duration)/(c + 1);                 for(size_t k = 0; k <= MAXSTACKS; ++k)                 {                     if(its.stacks[k] < min[j].stacks[k])                         min[j].stacks[k] = its.stacks[k];                     if(its.stacks[k] < max[j].stacks[k])                         max[j].stacks[k] = its.stacks[k];                     average[j].stacks[k] = ((average[j].stacks[k] * c) + its.stacks[k])/(c + 1);                 }             }         }     }          // Output to file     cout << "Simulation complete, check conduction_sim_output.txt for results" << endl;     file << "Cast interval range: " << minspread << " - " << maxspread << "(stepsize " << interval << ")" << endl;     file << "Iterations per interval: " << numits << endl;     file << "Results format: MINIMUM | AVERAGE | MAXIMUM" << endl;     for(size_t c = 0; c < steps; ++c)     {         file << "--------------------------------------" << endl;         file << "Cast Interval:   " << minspread + interval*c << endl;         file << "Duration:        " << min[c].duration << " | " << average[c].duration << " | " << max[c].duration << endl;         avg = 0;         for(size_t k = 0; k <= MAXSTACKS; ++k)         {             file << "Sec at " << k << " Stacks: "  << min[c].stacks[k] << " | " << average[c].stacks[k] << " | " << max[c].stacks[k] << endl;             avg += average[c].stacks[k]*k;         }         file << "Average stacks: " << avg/average[c].duration << endl;     }               file.close();          return 0; } // ============================================================================ // ---------------------------------------------------------------------------- iteration sim(size_t duration, double interval) {     iteration it;     size_t stacks = 0;     double stackdur = 0;          it.duration = 0;     for(size_t k = 0; k <= MAXSTACKS; ++k)         it.stacks[k] = 0;          // Seed random     srand(time(NULL));          while(it.duration < duration)     {         if((rand()%32768)/32767.0 < CHANCE)         {             stackdur = DURATION;             if(stacks < MAXSTACKS)                 stacks++;         }         it.duration += interval;                      if(stackdur > interval)         {             it.stacks[stacks] += interval;             stackdur -= interval;         }         else         {             it.stacks[stacks] += stackdur;             it.stacks[0] += interval - stackdur;             stackdur = 0;             stacks = 0;         }              }              return it; } // ----------------------------------------------------------------------------```

Even Angels must kill from time to time...
01-08-2012, 10:28 AM (This post was last modified: 01-08-2012 10:32 AM by lostdummy.)
Post: #14
 lostdummy Respected Member Posts: 100 Joined: Nov 2011 Reputation: 1
RE: DPS Excel calculator for SI Sorcerer
(01-08-2012 09:11 AM)Kor Wrote:  Here's the updated data with the rebuilt simulator (code below). Sim now casts every seconds, rather than randomly at a chance designed to meet that interval. Slightly less accurate representation of reality, significantly less chaotic and thus more reliable results:

I did simulation also, to double check numbers, and results are :

Code:
```Cst     Cst/      Avg every     buff   stacks ----------------------- 01.5    20.00    2.910 03.0    10.00    2.662 04.5    06.67    2.267 06.0    05.00    1.827 07.5    04.00    1.493 09.0    03.33    1.349 10.0    03.00    1.101 15.0    02.00    0.682 20.0    01.50    0.540 25.0    01.20    0.456 30.0    01.00    0.300 -----------------------```

Second column is 'number of casts per buff duration' , essentially number of LS per 30sec - since I used that metrics in my interpolation data table in excel. But this table I simulated in 'cast every X sec' increments, to be similar to your results.

Results appear fairly similar, although there is slight difference. My simulation did 1 million runs for each data point, and each run did all casts in one 300sec fight - so for 1.5sec casts thats 200 steps per run, while for 30sec casts that is 10 steps per run. Also, results are exactly same (at 3 decimal points) every run (and each run randomize different seed).

But numbers are close enough that we can assume they will be accurate for excel interpolation ;p

Just in case, here is my code:

Code:
```begin   nSim:=1000000;   castEvery:=1.5;   mymsg('  Cst     Cst/      Avg');   mymsg('every     buff   stacks');   mymsg('-----------------------');   while  (castEvery<=30)do   begin     nCstPerBuff:=30/castEvery     TotTicks:=round(10*nCstPerBuff);  // 300sec     aRes:=0;     Randomize;     ct:=0;     for ni:=1 to nSim do     begin       nTicksLeft:=TotTicks;       stack:=0;       avgStack:=0;       nTicksNoProc:=0;       while nTicksLeft>0 do       begin         // check proc         if random<=0.3 then         begin           stack:=stack+1;           if stack>3 then stack:=3;           nTicksNoProc:=0;         end;         // check if buff will drop before next tick, and use partial coverage         inc(nTicksNoProc);         if (nTicksNoProc>= nCstPerBuff) then         begin           avgStack:=avgStack+(1-(nTicksNoProc- nCstPerBuff))*stack;           stack:=0;         end else           // add current stack count, based on previous tick state           avgStack:=avgStack+stack;         //next         dec(nTicksLeft);       end;       aRes:=aRes+avgStack/totTicks;     end;     aRes:=aRes/nSim;     mymsg(FormatFloat(' '+'00.0',castEvery)+'    '+FormatFloat('00.00',nCstPerBuff)+'    '+FormatFloat('0.000',aRes));     // next step     if castEvery<10 then castEvery:=castEvery+1.5                       else castEvery:=castEvery+5;     if CastEvery=10.5 then CastEvery:=10;   end; end;```
01-08-2012, 10:30 AM
Post: #15
 Kaedis Posting Freak Posts: 1,587 Joined: Sep 2011 Reputation: 7
RE: DPS Excel calculator for SI Sorcerer
Quote:Results appear fairly similar, although there is slight difference. My simulation did 1 million runs for each data point, and each run did all casts in one 300sec fight - so for 1.5sec casts thats 200 steps per run, while for 30sec casts that is 10 steps per run.

I should note, for my 10-30 data points, I did a million iterations each as well, though mine have variable durations between 180 and 300.

Even Angels must kill from time to time...
01-08-2012, 11:00 AM
Post: #16
 lostdummy Respected Member Posts: 100 Joined: Nov 2011 Reputation: 1
RE: DPS Excel calculator for SI Sorcerer
(01-08-2012 10:30 AM)Kor Wrote:  I should note, for my 10-30 data points, I did a million iterations each as well, though mine have variable durations between 180 and 300.

Very good point - duration does have effect on average stacks, and I only calculated for 300sec (ie same as default fight duration on excel).

For example, for 450sec fight duration, results are:

Code:
```Cst     Cst/      Avg every     buff   stacks ----------------------- 01.5    20.00    2.938 03.0    10.00    2.708 04.5    06.67    2.315 06.0    05.00    1.866 07.5    04.00    1.524 09.0    03.33    1.381 10.0    03.00    1.122 15.0    02.00    0.691 20.0    01.50    0.547 25.0    01.20    0.463 30.0    01.00    0.300 -----------------------```

while for 180sec fight :

Code:
```Cst     Cst/      Avg every     buff   stacks ----------------------- 01.5    20.00    2.854 03.0    10.00    2.570 04.5    06.67    2.170 06.0    05.00    1.749 07.5    04.00    1.431 09.0    03.33    1.288 10.0    03.00    1.060 15.0    02.00    0.663 20.0    01.50    0.525 25.0    01.20    0.444 30.0    01.00    0.300 -----------------------```

Close to each other, but not exactly same. And just as in excel, I dont really know what will be average operation boss fight duration ;p
01-08-2012, 12:05 PM
Post: #17
 Kaedis Posting Freak Posts: 1,587 Joined: Sep 2011 Reputation: 7
RE: DPS Excel calculator for SI Sorcerer
Quote:Close to each other, but not exactly same. And just as in excel, I dont really know what will be average operation boss fight duration ;p

That could simply be deviation in the randomness. Theoretically, any multiple of 30 seconds should have roughly the same values, with longer fights coming closer to the actual value (since we're starting at 0 stacks).

Even Angels must kill from time to time...
01-08-2012, 08:46 PM (This post was last modified: 01-08-2012 09:14 PM by lostdummy.)
Post: #18
 lostdummy Respected Member Posts: 100 Joined: Nov 2011 Reputation: 1
RE: DPS Excel calculator for SI Sorcerer
(01-08-2012 12:05 PM)Kor Wrote:
Quote:Close to each other, but not exactly same. And just as in excel, I dont really know what will be average operation boss fight duration ;p

That could simply be deviation in the randomness. Theoretically, any multiple of 30 seconds should have roughly the same values, with longer fights coming closer to the actual value (since we're starting at 0 stacks).

Exactly - any multiple but initial one - and that explain why shorter duration fights have lower average stacks. For 180sec fight, initial 30sec (with lower average stack) is significant part, compared to 450sec fight.

But it would also suggest that number difference is not just due to deviation in randomness, which my simulation support - even for low fight duration, when I run simulation I always get same (lower) numbers up to 2nd-3rd decimal.

Since we will not have fights getting infinitely long, if there is actual difference in stack coverage at some realistical fight durations (for example, 3min vs 6min), I wonder if I should model that too in excel... or just take average value - or value at most usual fight duration.

I could model that behavior also , by making "2 dimensional interpolation" in excel - for example, for fight duration at 2,3,4,5,7,10 min ... but I'm not sure if it pays to complicate calculation of one value so much, where difference from 'default' 300sec would be fairly small, and final influence of that difference on DPS even smaller.

*Edit* Just compared values from 3min, 4min, 5min and 6min stacks, and roughly compared to 5min values it looks like:
Code:
```3 min: -5% 4 min: -1.5% 5 min: 6 min: +1% 10min: +3%```
Since those values influence DPS as multiple of 1%, it means if I use 5min values for 6min fight, I introduce error in DPS of 0.01%. Even for worse case, 3min fight, error in DPS from using 5min values is only 0.05%.
Therefore it seem safe to use only value set from 300sec fight for interpolation.
01-08-2012, 09:43 PM (This post was last modified: 01-09-2012 06:15 AM by lostdummy.)
Post: #19
 lostdummy Respected Member Posts: 100 Joined: Nov 2011 Reputation: 1
RE: DPS Excel calculator for SI Sorcerer
I uploaded new version, with Conduction interpolated based on this simulation data.

In general, reducing (incorrect) effect of Conduction from 3% to these lower values, resulted in slightly lowering Lightning build DPS. And since all builds are very close in DPS, small changes in DPS can change which build appears to be 'best DPS'.

For example, now Lightning shows as some 3% more DPS than Madness, and some 3% lower DPS than Balanced build.

*Edit*
Also found that CL in excel was not benefiting from 20% Wrath bonus if used under Wrath instead of under Light Storm.. and after fixing that, using more CLs are beneficial even on Balanced build, which has side effect of making that build also force limited unless Light Effusion is talented. So returned that skill to default Balanced build instead of Creeping Death and 1pt Force Horrors.
01-09-2012, 04:37 PM
Post: #20
 Pestulan Junior Member Posts: 12 Joined: Jan 2012 Reputation: 0
RE: DPS Excel calculator for SI Sorcerer
(01-08-2012 09:43 PM)lostdummy Wrote:  I uploaded new version, with Conduction interpolated based on this simulation data.

In general, reducing (incorrect) effect of Conduction from 3% to these lower values, resulted in slightly lowering Lightning build DPS. And since all builds are very close in DPS, small changes in DPS can change which build appears to be 'best DPS'.

For example, now Lightning shows as some 3% more DPS than Madness, and some 3% lower DPS than Balanced build.

*Edit*
Also found that CL in excel was not benefiting from 20% Wrath bonus if used under Wrath instead of under Light Storm.. and after fixing that, using more CLs are beneficial even on Balanced build, which has side effect of making that build also force limited unless Light Effusion is talented. So returned that skill to default Balanced build instead of Creeping Death and 1pt Force Horrors.

I think you need to recheck your builds. The Balanced build currently has too many points spent. It's 3/17/24 atm, which is 3 too many.

To get Force Horrors 1/2, Death Mark, and Lingering Nightmares, you need 24 points in Madness. You have to fill 4 points in non-DPS talents to get to the 20pt tier. You've also spent 17 points in Lightning, but only list 16 (Lightning Spire or going 3/3 in Electric Induction are required before you can take Lightning Effusion).
 « Next Oldest | Next Newest »

Forum Jump:

User(s) browsing this thread: 1 Guest(s)