#!/sw/bin/python2.5


# $Id: catmodel.py 76 2007-06-09 08:23:24Z sas $


from numpy import *

import os


import pylab as p

import matplotlib.axes3d as p3


from random import random


class CatModel:

   

    def computeDps( self, ap, crit, duration = 1000, rip_combolimit = 4,

                    mob_mitigation = 0.25 ):

        pawDps = 56.4

        ap_to_dps = 0.0714286

        ap_to_rip = 0.24

        mangle_bonus = 1.3

        ooc_proc = 1./30

        str_to_ap = 2.472

        agi_to_ap = 1.03

        crit_rating_to_crit = 0.0004525

        agi_to_crit = 0.000412


        base_dmg = ( pawDps + ap * ap_to_dps ) * 1.1 * ( 1 - mob_mitigation )

        mangle_dmg = (( 1.6 * base_dmg + 264.0 ) * 1.2 ) * 1.1 * ( 1 - mob_mitigation )

        rip_dmg = (( ap * ap_to_rip + 1092.0 ) / 12.0 ) * 1.1

        shred_dmg = ( 2.25 * base_dmg + 405 ) * 1.1 * ( 1 - mob_mitigation )

       

        total_dmg = 0.0

        energy = 100

        mangle_on = 0

        rip_on = 0

        combo_pts = 0

        ooc_on = False

       

        for i in range(duration):

            #print 'time: %6i, dmg %5i, energy %3i, combo %i, mangle %2i, rip %2i, ooc %i' % ( i, total_dmg, energy, combo_pts, mangle_on, rip_on, ooc_on )

            # energy tick

            if i % 2 == 0:

                energy += 20

                if energy > 100:

                    energy = 100

           

            mangle_on -= 1

            rip_on -= 1

           

            # mangle

            if ( mangle_on <= 0 and

                 energy >= 40 and

                 combo_pts < rip_combolimit ):

               

                if random() <= crit:

                    total_dmg += 2.2*mangle_dmg

                    combo_pts += 2

                else:

                    total_dmg += mangle_dmg

                    combo_pts += 1

                mangle_on = 12


                if not ooc_on:

                    energy -= 40

                else:

                    ooc_on = False

               

                if random() <= ooc_proc:

                    ooc_on = True

           

            else:

                # rip

                if ( combo_pts >= rip_combolimit and

                       energy >= 30 and

                       rip_on <= 0 ):

   

                    rip_on = 12

                    combo_pts = 0

   

                    if not ooc_on:

                        energy -= 30

                    else:

                        ooc_on = False

                   

                    if random() <= ooc_proc:

                        ooc_on = True

               

                else:

                      

                    # shred

                    if energy >= 42 and mangle_on > 0:

                        

                        if random() <= crit:

                            total_dmg += 2.2 * shred_dmg * mangle_bonus

                            combo_pts += 2

                        else:

                            total_dmg += shred_dmg * mangle_bonus

                            combo_pts += 1

       

                        if not ooc_on:

                            energy -= 42

                        else:

                            ooc_on = False

       

                        if random() <= ooc_proc:

                            ooc_on = True

               

                    # white damage

                    if random() <= crit:

                        total_dmg += 2.2*base_dmg

                    else:

                        total_dmg += base_dmg

       

                    if random() <= ooc_proc:

                        ooc_on = True

                   

                    # rip ticks

                    if rip_on > 0:

                        if mangle_on > 0:

                            total_dmg += rip_dmg * mangle_bonus

                        else:

                            total_dmg += rip_dmg

       

        return total_dmg / duration



def plot_ap_crit():

    crit, ap = mgrid[28:38, 2000:3000:100]

    dps = []

    cat = CatModel()

    for c in [ i[0] for i in crit ]:

        print 'Processing crit chance: ', c

        row = []

        dps.append( row )

        for a in ap[0]:

            d = cat.computeDps( ap = a, crit = c/100., duration = 100*1000)

            row.append( d )


    dps = array( dps )

    fig=p.figure()

    ax = p3.Axes3D(fig)

    ax.plot_wireframe(ap,crit,dps)

    ax.set_xlabel('AP')

    ax.set_ylabel('Crit')

    ax.set_zlabel('dps')

   

    p.savefig('ap_crit.png')

    p.show()



import Gnuplot, Gnuplot.funcutils


def plot_agi_str():

    crit = arange(30, 40, 2)

    ap = arange(2000, 3000, 200)

    duration = 10*1000*1000

    agi_inc = 50

    str_inc = 50


    diff = []

    cat = CatModel()

    for c in crit:

        print 'Processing crit chance: ', c

        row = []

        diff.append( row )

        for a in ap:

            dps_agi = cat.computeDps( ap = a + agi_inc * 1.03,

                                      crit = c/100. + agi_inc * 0.000412,

                                      duration = duration )

            dps_str = cat.computeDps( ap = a + str_inc * 2.472,

                                      crit = c/100.,

                                      duration = duration )

            row.append( dps_agi - dps_str )


    g = Gnuplot.Gnuplot( debug=1 )

    g('set parametric')

    g('set data style lines')

    g('set hidden')

    g('set contour base')

    g.title('Agi-Str dps gain')

    g.xlabel('AP')

    g.ylabel('Crit')

    g.splot( Gnuplot.GridData( diff, ap, crit, binary = 0 ) )

    g.hardcopy('agi_str.ps', enhanced=1, color=1)




if __name__ == '__main__':

    plot_ap_crit()

    plot_agi_str()