Calculator:Revolution/Details

## Algorithm details

This section mostly covers a discussion on the algorithms used to calculate AADPT and to find cycles and preambles.

### Basic AADPT calculation

The basic AADPT calculation is fairly simple.

It can be broken down into a few sections:

* Pre-loop stuff (reset abilities, setup variables)
* The loop
	+ Reducing cooldowns
	+ Finding the next ability
	+ Incrementing the counters
* Post-loop error checking and returning

Psuedocode

```
FUNCTION (bar)  //bar is an array of Ability objects
  DEFINE time=0, incr=0, damage=0, stunned=0, next, broke=false
  WHILE time < simulation_ticks  //from settings, number of ticks to run for
    reduce cooldown on all abilities by incr (but not below 0)
	reduce stunned by incr (but not below 0)

    SET next = null  //reset next
	FOREACH ability IN bar
	  IF ability is off-cooldown
	    SET next = ability
		break
	IF next is null
	  SET broke = true  //the bar doesn't work
	  break

	//activate ability
	put next on cooldown
	SET incr = duration of next
	INCREMENT time BY incr

	IF stunned > 0 AND next is a stunbuffed ability
	  INCREMENT damage BY stun damage of next
	ELSE
	  INCREMENT damage BY damage of next

	IF stuns are are enabled AND next stuns
	  SET stunned = stun duration of next

  IF not broke
    RETURN damage/time

  RETURN not working error

```

Obviously, extra parts are needed to, for example, make sure every ability is reset before starting, and to turn an array of ability names (strings) into an array of Ability objects.

### Cycle

Finding the cycle is more complex, and consists of several sections.

A basic overview is as follows:

* Simulate revolution to generate a long string of integers
* Find the cycle in this string
	+ Reorder the cycle to a more logical representation
* Check for a preamble
	+ If there is one, find it
* Calculate the AADPT of the cycle
	+ and the preamble, if there is one

Simulating revolution
This is essentially the same as the above, but instead of capturing damage, we capture the index of the ability in the bar into a string. It also makes note of how many abilities are used more than twice (if an ability is only used once or twice, it is in the preamble).

Finding the cycle and preamble

```
FUNCTION (v)  //string of integers
  DEFINE c="", l = length of v, i
  WHILE cycle not found && l >= 2*i
    INCREMENT i BY 1
	SET c = last i characters of v
	IF all abilities have been used AND the [last 2i characters of v] are [c repeated]
	  SET hascycle = true

  IF no cycle was found
    RETURN error

  IF [c repeated] contains the first [length of c] integers
    SET haspreamble = false
	SET c = first [length of c] characters of v  //reorder
  ELSE
    SET haspreamble = true
	SET jind = first occurence of c in v
	SET c2 = copy of c
	FOR the length of c2
	  rotate c2 by 1 character
	  SET jind2 = first occurence of c2 in v
	  IF jind2 not found
	    RETURN error
	  IF jind2 < jind
	    INCREMENT ms BY difference of jind2 and jind
		SET jind = jind2

    SET preamble = first jind characters of v
	IF ms > 0
	  rotate c by ms characters

```

Calculate AADPT
Very similar to calculating it normally, but only loops for the length of the cycle and preamble

```
FUNCTION (bar)  //bar is an array of Ability objects
  DEFINE time=0, incr=0, damage=0, s=""
  FOR length of cycle
    SET ability = ability correspnding to character i
	INCREMENT time BY duration

	IF ability is currently stunbuffed
	  INCREMENT damage BY stun damage of ability
	  INCREMENT s BY ability name +'*'
	ELSE
	  INCREMENT damage BY damage of ability
	  INCREMENT s BY ability name

  IF haspreamble
    FOR length of preamble
      SET ability = ability correspnding to character i
	  INCREMENT time BY duration

	  IF ability is currently stunbuffed
	    INCREMENT damage BY stun damage of ability
	    INCREMENT s BY ability name +'*'
	  ELSE
	    INCREMENT damage BY damage of ability
	    INCREMENT s BY ability name

```

### Finding the optimal bars

These algorithms are easily adapted to a form that is easily ran repeatedly to find an optimal bar for a given list of abilities.

There's two ways to check bars:

* Repeatedly randomise the list and calculate, a specific number of times
While it doesn't guarantee finding the true optimal bar, it usually does, and doing this limits the time required (since it is randomised a specific, predetermined number of times)
* Check every permutation of the list and calculate
This will always find the true optimal bar, but the more available abilities there are, the longer it will take -e.g. 9 abilities gives 9! = 362880 permutations. This can take a long time to check, especially on lower-end computers. However, many situations don't need that many abilities so the issue doesn't arrive, making this the preferred method.

The optimal bars given on revolution were calculated using this method.