Advertisement
Cascadi

Machinist Simulator

Jun 23rd, 2015
3,385
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 16.25 KB | None | 0 0
  1. #Simulator of Machinist DPS
  2. #Cascadi @ FFXIV Forums
  3. #Last updated: 7/14/2015
  4.  
  5. import random
  6. random.seed(0)
  7.  
  8. #you can edit this
  9. #dex potion and crits implemented
  10. #stats implemented
  11. #once you finish inputing your opener, cds will be used whenever they are available, input as a string with _ for spaces
  12. #ex. prev_custom_opener = ["reload","split_shot","hawks_eye"]
  13. #gauss_barrel_start means if you will start with gauss barrel on
  14. #starting_ammo means how much ammo you start with
  15. #gcd means what your Recast timer (Global Cooldown) is
  16. #gauss_barrel_always_on means if you'll have Gauss Barrel up for the whole time instead of toggling it on and off
  17. #how_many_sims means how many times you want to run the simulation
  18. gauss_barrel_start = True
  19. prev_custom_opener = ["blood_for_blood","hypercharge","gauss_round","hot_shot","raging_strikes","hawks_eye","lead_shot","rapid_fire","reload","split_shot","wildfire","slug_shot","potion","split_shot","reassemble","clean_shot","quick_reload","gauss_round","slug_shot","ricochet","head_graze","clean_shot","blank"]
  20. starting_ammo = 0
  21. parse_time = 240
  22. gauss_barrel_always_on = False
  23. how_many_sims = 1
  24. DEX = 955.0
  25. AA_DMG = 57.2
  26. AA_DELAY = 2.64
  27. SKILLSPEED = 611.0
  28. DET = 450.0
  29. CRIT = 679.0
  30. WD = 65.0
  31.  
  32. #don't edit the below
  33. gcd = 0
  34. TEMP_DEX = 0.0
  35. list_of_results = []
  36. list_of_skills = []
  37. custom_opener = []
  38. ammo = 0
  39. parse_tick = 0.01
  40. gauss_barrel = False
  41. reassemble = False
  42.  
  43. hot_shot = 300
  44. lead_shot = 0
  45. lead_shot_cd = 300
  46.  
  47. blood_for_blood = 0
  48. raging_strikes = 0
  49. hypercharge = 0
  50. hawks_eye = 0
  51. rapid_fire = 0
  52. wildfire = 0
  53. potion = 0
  54. reassemble = False
  55.  
  56. aa = 0
  57. wildfire_damage = 0.0
  58. turret_hit = 0
  59.  
  60. #rotation
  61. def rotations(temp_time):
  62.    
  63.     #variables
  64.     global hot_shot
  65.     global lead_shot
  66.     global lead_shot_potency
  67.     global lead_shot_cd
  68.     global blood_for_blood
  69.     global raging_strikes
  70.     global hypercharge
  71.     global hawks_eye
  72.     global rapid_fire
  73.     global wildfire
  74.     global reassemble
  75.     global potion
  76.     global wildfire_damage
  77.     global gauss_barrel
  78.     global starting_ammo
  79.     global ammo
  80.        
  81.     global aa
  82.     global DEX
  83.     global TEMP_DEX
  84.     global AA_DMG
  85.     global AA_DELAY
  86.     global CRIT
  87.     global DET
  88.     global SKILLSPEED
  89.     global WD
  90.     global gcd
  91.    
  92.     global parse_tick
  93.     global parse_time
  94.     global total_damage
  95.     global list_of_skills
  96.    
  97.     TEMP_DEX = DEX
  98.     ammo = starting_ammo
  99.     custom_opener = prev_custom_opener[:]
  100.    
  101.     slug_shot = False
  102.     clean_shot = False
  103.    
  104.     blood_for_blood_cd = 900
  105.     raging_strikes_cd = 1800
  106.     hypercharge_cd = 1200
  107.     hawks_eye_cd = 900
  108.     rapid_fire_cd = 900
  109.     wildfire_cd = 900
  110.     reassemble_cd = 600
  111.     potion_cd = 2700
  112.  
  113.     ricochet = 600
  114.     blank = 300
  115.     head_graze = 250
  116.     gauss_round = 200
  117.     remover = 0
  118.     turret_delay = 0
  119.     hot_shot = 300
  120.     lead_shot = 0
  121.     lead_shot_cd = 300
  122.  
  123.     m_reload = 600
  124.     quick_reload = 300
  125.  
  126.     rapid_fire_count = 0
  127.  
  128.     t_gcd = gcd
  129.     c_gcd = 0
  130.     o_gcd = 0
  131.  
  132.     turret_potency = 80.0
  133.     total_damage = 0.0
  134.                
  135.     #let's calculate gcd
  136.     gcd = 2.50256-(0.01*(SKILLSPEED-354.0)/26.5)
  137.    
  138.     #start with gauss barrel?
  139.     if(gauss_barrel_start == True):
  140.         list_of_skills.append("gauss_barrel_on")
  141.         gauss_barrel = True
  142.        
  143.     #parse update
  144.     while(temp_time > 0):
  145.        
  146.         #gauss barrel always on?
  147.         if(gauss_barrel_always_on == True and gauss_barrel == False):
  148.             list_of_skills.append("gauss_barrel_on")
  149.             gauss_barrel = True
  150.            
  151.         temp_time -= parse_tick
  152.         c_gcd += parse_tick
  153.         o_gcd += parse_tick
  154.        
  155.         hot_shot += parse_tick
  156.         lead_shot_cd += parse_tick
  157.        
  158.         blood_for_blood_cd += parse_tick
  159.         raging_strikes_cd += parse_tick
  160.         hypercharge_cd += parse_tick
  161.         hawks_eye_cd += parse_tick
  162.         rapid_fire_cd += parse_tick
  163.         wildfire_cd += parse_tick
  164.         reassemble_cd += parse_tick
  165.         quick_reload += parse_tick
  166.         potion_cd += parse_tick
  167.         m_reload += parse_tick
  168.         ricochet += parse_tick
  169.         gauss_round += parse_tick
  170.        
  171.         blood_for_blood -= parse_tick
  172.         raging_strikes -= parse_tick
  173.        
  174.         hypercharge -= parse_tick
  175.         hawks_eye -= parse_tick
  176.         wildfire -= parse_tick
  177.         potion -= parse_tick
  178.        
  179.         #let's calculate turret damage
  180.         turret_delay += parse_tick
  181.         if(turret_delay >= 3.0 and temp_time > 0):
  182.             potency_mod = 1.0
  183.             turret_hit = ((turret_potency/100)*(WD/25+1)*(TEMP_DEX/9*1.2)*(DET/7290+1)*potency_mod)-1.5
  184.             if(random.uniform(0.0,100.0) <= ((CRIT-354)*0.0233)+4.9511233):
  185.                 potency_mod *= ((CRIT-354)*0.000233)+1.4483610
  186.             if(hypercharge > 0):
  187.                 potency_mod *= 1.05
  188.             if(hypercharge > 10):
  189.                 turret_hit += ((turret_potency/100)*(WD/25+1)*(TEMP_DEX/9*1.2)*(DET/7290+1)*potency_mod)-1.5
  190.             if(wildfire_cd > 0):
  191.                 wildfire_damage += turret_hit
  192.             total_damage += turret_hit
  193.             list_of_skills.append("turret hit - " + str(turret_hit))
  194.             turret_delay = 0
  195.                
  196.         #let's check lead shot DoT
  197.         lead_shot -= parse_tick
  198.         if(lead_shot % 3 <= parse_tick and lead_shot > 0):
  199.             potency_mod = 1.0
  200.             if(random.uniform(0.0,100.0) <= ((CRIT-354)*0.0233)+4.9511233):
  201.                 potency_mod *= ((CRIT-354)*0.000233)+1.4483610
  202.             total_damage += (lead_shot_potency * potency_mod)
  203.             if(wildfire > 0):
  204.                 wildfire_damage += (lead_shot_potency * potency_mod)
  205.        
  206.         #GB recast time
  207.         remover -= parse_tick
  208.        
  209.         #if no custom opener defined
  210.         if(len(custom_opener) == 0):
  211.            
  212.             # gcd skill rotation
  213.             if(c_gcd >= t_gcd):
  214.                
  215.                 if(rapid_fire > 0):
  216.                     rapid_fire -= 1
  217.                
  218.                 c_gcd = 0
  219.                
  220.                 if(hot_shot >= 30):
  221.                     add_potency("hot_shot")
  222.                     if(ammo > 0):
  223.                         ammo -= 1
  224.                     hot_shot = 0
  225.                 elif(lead_shot_cd >= 30):
  226.                     add_potency("lead_shot")
  227.                     if(ammo > 0):
  228.                         ammo -= 1
  229.                     lead_shot = 30 + parse_tick
  230.                     lead_shot_cd = 0
  231.                 else:
  232.                     if(clean_shot == True):
  233.                         if(ammo > 0):
  234.                             if(reassemble_cd >= 60):
  235.                                 list_of_skills.append("reassemble")
  236.                                 reassemble = True
  237.                                 add_potency("clean_shot")
  238.                                 clean_shot = False
  239.                                 reassemble_cd = 0
  240.                                 ammo -= 1
  241.                             else:
  242.                                 add_potency("clean_shot")
  243.                                 clean_shot = False
  244.                         elif(ammo == 0):
  245.                             add_potency("clean_shot")
  246.                             clean_shot = False
  247.                        
  248.                     elif(slug_shot == True):
  249.                         add_potency("slug_shot")
  250.                         slug_shot = False
  251.                         if(ammo > 0):
  252.                             ammo -= 1
  253.                             clean_shot = True
  254.                         else:
  255.                             rng = random.randint(0, 100)
  256.                             if(rng >= 50):
  257.                                 clean_shot = True
  258.                                
  259.                     else:
  260.                         add_potency("split_shot")
  261.                         if(ammo > 0):
  262.                             ammo -= 1
  263.                             slug_shot = True
  264.                         else:
  265.                             rng = random.randint(0, 100)
  266.                             if(rng >= 50):
  267.                                 slug_shot = True
  268.                                
  269.             # buffs and mmo
  270.             if(o_gcd >= 1):
  271.                 o_gcd = 0
  272.                 if(ammo < 5):
  273.                     if(m_reload >= 60 and ammo == 0):
  274.                         list_of_skills.append("reload")
  275.                         m_reload = 0
  276.                         ammo = 5
  277.                     elif(quick_reload >= 30 and slug_shot == True):
  278.                         list_of_skills.append("quick_reload")
  279.                         quick_reload = 0
  280.                         ammo += 1
  281.                 if(potion_cd >= 270):
  282.                     list_of_skills.append("potion")
  283.                     potion = 15
  284.                     potion_cd = 0
  285.                 if(raging_strikes_cd >= 180):
  286.                     list_of_skills.append("raging_strikes")
  287.                     raging_strikes = 20
  288.                     raging_strikes_cd = 0
  289.                 elif(hawks_eye_cd >= 90):
  290.                     list_of_skills.append("hawks_eye")
  291.                     hawks_eye = 20
  292.                     hawks_eye_cd = 0
  293.                 elif(blood_for_blood_cd >= 90):
  294.                     list_of_skills.append("blood_for_blood")
  295.                     blood_for_blood = 20
  296.                     blood_for_blood_cd = 0
  297.                 elif(hypercharge_cd >= 120):
  298.                     list_of_skills.append("hypercharge")
  299.                     hypercharge = 25
  300.                     hypercharge_cd = 0
  301.                 elif(wildfire_cd >= 90 and gauss_barrel_always_on == False and gauss_barrel == False):
  302.                     list_of_skills.append("gauss_barrel_on")
  303.                     gauss_barrel = True
  304.                     remover = 15
  305.                 elif(wildfire_cd >= 90):
  306.                     list_of_skills.append("wildfire")
  307.                     wildfire = 15
  308.                     wildfire_cd = 0
  309.                 elif(rapid_fire_cd >= 90):
  310.                     list_of_skills.append("rapid_fire")
  311.                     rapid_fire_count = 3
  312.                     rapid_fire_cd = 0
  313.                 elif(gauss_barrel == True):
  314.                     if(ricochet >= 60):
  315.                         add_potency("ricochet")
  316.                         ricochet = 0
  317.                     elif(gauss_round >= 20):
  318.                         add_potency("gauss_round")
  319.                         gauss_round = 0
  320.                     elif(head_graze >= 25):
  321.                         add_potency("head_graze")
  322.                         head_graze = 0
  323.                     elif(blank >= 30):
  324.                         add_potency("blank")
  325.                         blank = 0
  326.                     elif(gauss_barrel_always_on == False and remover <= parse_tick):
  327.                         list_of_skills.append("gauss_barrel_off")
  328.                         gauss_barrel = False
  329.                 elif(head_graze >= 25):
  330.                     add_potency("head_graze")
  331.                     head_graze = 0
  332.                 elif(blank >= 30):
  333.                     add_potency("blank")
  334.                     blank = 0
  335.            
  336.             #auto attacks
  337.             if(gauss_barrel == False):
  338.                 aa += parse_tick
  339.                 if(aa >= AA_DELAY):
  340.                     add_potency("auto")
  341.                     aa = 0
  342.            
  343.             #apply wildfire damage
  344.             if(wildfire > 0 and wildfire <= parse_tick):
  345.                 total_damage += wildfire_damage * 0.25
  346.                 list_of_skills.append("wildfire off - " + str(wildfire_damage * 0.25))
  347.                 wildfire_damage = 0
  348.                 wildfire = 0
  349.                
  350.             if(rapid_fire > 0):
  351.                 t_gcd = 1.5
  352.             else:
  353.                 t_gcd = gcd
  354.                
  355.         #custom opener happens
  356.         elif(len(custom_opener) > 0):
  357.            
  358.             list_of_buffs = ["reload","quick reload","raging_strikes","hawks_eye","hypercharge","blood_for_blood","wildfire","rapid_fire","gauss_barrel","gauss_round","ricochet","blank","head_graze"]
  359.             list_of_weaponskills = ["hot_shot","lead_shot","split_shot","slug_shot","clean_shot"]
  360.            
  361.             #buffs
  362.             if(o_gcd >= 1):
  363.                 o_gcd = 0
  364.                 if(custom_opener[0] == "reload"):
  365.                     list_of_skills.append("reload")
  366.                     m_reload = 0
  367.                     ammo = 5
  368.                 elif(custom_opener[0] == "quick_reload"):
  369.                     list_of_skills.append("quick_reload")
  370.                     quick_reload = 0
  371.                     ammo += 1
  372.                 if(custom_opener[0] == "reassemble"):
  373.                     list_of_skills.append("reassemble")
  374.                     reassemble = True
  375.                     reassemble_cd = 0
  376.                 elif(custom_opener[0] == "raging_strikes"):
  377.                     list_of_skills.append("raging_strikes")
  378.                     raging_strikes = 20
  379.                     raging_strikes_cd = 0
  380.                 elif(custom_opener[0] == "hawks_eye"):
  381.                     list_of_skills.append("hawks_eye")
  382.                     hawks_eye = 20
  383.                     hawks_eye_cd = 0
  384.                 elif(custom_opener[0] == "blood_for_blood"):
  385.                     list_of_skills.append("blood_for_blood")
  386.                     blood_for_blood = 20
  387.                     blood_for_blood_cd = 0
  388.                 elif(custom_opener[0] == "hypercharge"):
  389.                     list_of_skills.append("hypercharge")
  390.                     hypercharge = 25
  391.                     hypercharge_cd = 0
  392.                 elif(custom_opener[0] == "wildfire"):
  393.                     list_of_skills.append("wildfire")
  394.                     wildfire = 15
  395.                     wildfire_cd = 0
  396.                 elif(custom_opener[0] == "rapid_fire"):
  397.                     list_of_skills.append("rapid_fire")
  398.                     rapid_fire_count = 3
  399.                     rapid_fire_cd = 0
  400.                 elif(custom_opener[0] == "gauss_barrel" and gauss_barrel_always_on == False):
  401.                     if(gauss_barrel == True):
  402.                         list_of_skills.append("gauss_barrel_off")
  403.                         gauss_barrel = False
  404.                     else:
  405.                         list_of_skills.append("gauss_barrel_on")
  406.                         gauss_barrel = True
  407.                         remover = 15
  408.                 elif(custom_opener[0] == "potion"):
  409.                     list_of_skills.append("potion")
  410.                     potion = 15
  411.                     potion_cd = 0
  412.                 elif(custom_opener[0] == "gauss_round"):
  413.                     add_potency(custom_opener[0])
  414.                     gauss_round = 0
  415.                 elif(custom_opener[0] == "ricochet"):
  416.                     add_potency(custom_opener[0])
  417.                     ricochet = 0
  418.                 elif(custom_opener[0] == "blank"):
  419.                     add_potency(custom_opener[0])
  420.                     blank = 0
  421.                 elif(custom_opener[0] == "head_graze"):
  422.                     add_potency(custom_opener[0])
  423.                     head_graze = 0
  424.                    
  425.                 #done with custom opener
  426.                 custom_opener.pop(0)
  427.            
  428.             # gcd skill rotation
  429.             if(c_gcd >= t_gcd):
  430.                 if(custom_opener[0] in list_of_weaponskills):
  431.                     if(rapid_fire > 0):
  432.                         rapid_fire -= 1
  433.                    
  434.                     c_gcd = 0
  435.                     if(ammo > 0):
  436.                         ammo -= 1
  437.                     add_potency(custom_opener[0])
  438.                
  439.                     if(custom_opener[0] == "hot_shot"):
  440.                         hot_shot = 0
  441.                     elif(custom_opener[0] == "lead_shot"):
  442.                         lead_shot = 30 + parse_tick
  443.                         lead_shot_cd = 0
  444.                    
  445.                     #done with custom opener
  446.                     custom_opener.pop(0)
  447.                            
  448.             #auto attacks
  449.             if(gauss_barrel == False):
  450.                 aa += parse_tick
  451.                 if(aa >= AA_DELAY):
  452.                     add_potency("auto")
  453.                     aa = 0
  454.            
  455.             #apply wildfire damage
  456.             if(wildfire <= 0):
  457.                 total_damage += wildfire_damage * 0.25
  458.                 wildfire_damage = 0
  459.            
  460.             #rapid fire gcd mod
  461.             if(rapid_fire > 0):
  462.                 t_gcd = 1.5
  463.             else:
  464.                 t_gcd = gcd
  465.                    
  466.         #reset DEX mods
  467.         if(hawks_eye <= parse_tick and potion <= parse_tick):
  468.             TEMP_DEX = DEX
  469.            
  470.     if(temp_time <= 0):
  471.         list_of_results.append(total_damage / parse_time)
  472.         print "The total damage was: " + str(total_damage) + " over " + str(parse_time) + " seconds. " + "DPS: " + str(total_damage / parse_time)
  473.         print "The skill rotation was: " + str(list_of_skills)
  474.  
  475. #uses skill
  476. def add_potency(skill):
  477.    
  478.     #variables
  479.     global hot_shot
  480.     global lead_shot
  481.     global lead_shot_potency
  482.     global lead_shot_cd
  483.     global blood_for_blood
  484.     global raging_strikes
  485.     global hypercharge
  486.     global hawks_eye
  487.     global rapid_fire
  488.     global wildfire
  489.     global reassemble
  490.     global wildfire_damage
  491.     global potion
  492.     global gauss_barrel
  493.     global ammo
  494.     global aa
  495.     global AA_DELAY
  496.     global gcd
  497.    
  498.     global total_damage
  499.     global list_of_skills
  500.    
  501.     global DEX
  502.     global TEMP_DEX
  503.     global DET
  504.     global AA_DMG
  505.     global AA_DELAY
  506.     global SKILLSPEED
  507.     global CRIT
  508.     global WD
  509.    
  510.     potency_mod = 1.0
  511.     if(hot_shot > 0):
  512.         potency_mod *= 1.05
  513.     if(blood_for_blood > 0):
  514.         potency_mod *= 1.1
  515.     if(raging_strikes > 0):
  516.         potency_mod *= 1.2
  517.     if(hypercharge > 0):
  518.         potency_mod *= 1.05
  519.     if(hawks_eye > 0 and potion > 0):
  520.         TEMP_DEX = DEX * 1.15 + 84
  521.     elif(hawks_eye > 0):
  522.         TEMP_DEX = DEX * 1.15
  523.     elif(potion > 0):
  524.         TEMP_DEX = DEX + 84
  525.     if(gauss_barrel):
  526.         potency_mod *= 1.3
  527.     if(reassemble):
  528.         potency_mod *= ((CRIT-354)*0.000233)+1.4483610
  529.         reassemble = False
  530.     elif(reassemble == False):
  531.         if(random.uniform(0.0,100.0) < (((CRIT-354)*0.0233)+4.9511233)):
  532.             potency_mod *= ((CRIT-354)*0.000233)+1.4483610
  533.    
  534.     temp_damage = 0
  535.     ammo_potency = 0
  536.     temp_potency = 0
  537.     eligible_skills = ["hot_shot","lead_shot","split_shot","slug_shot","clean_shot"]
  538.     if(ammo > 0 and skill in eligible_skills):
  539.         ammo_potency += 20.0
  540.    
  541.     if(skill == "auto"):
  542.         temp_damage = ((AA_DMG/33.04+1)*(TEMP_DEX/6.92)*(DET/6715+1)*(1) * potency_mod) - (1.5*AA_DELAY)
  543.            
  544.     if(skill == "hot_shot"):
  545.         temp_potency += (120.0 + ammo_potency)
  546.     if(skill == "lead_shot"):
  547.         temp_potency += (40.0 + ammo_potency)
  548.         lead_shot_potency = ((45.0/100)*(WD/25+1)*(TEMP_DEX/9*1.2)*(DET/7290+1)*potency_mod*(1+(SKILLSPEED-354.0)*0.000138))-1.5
  549.        
  550.     if(skill == "split_shot"):
  551.         temp_potency += (140.0 + ammo_potency)
  552.     if(skill == "slug_shot"):
  553.         temp_potency += (180.0 + ammo_potency)
  554.     if(skill == "clean_shot"):
  555.         temp_potency += (200.0 + ammo_potency)
  556.        
  557.     if(skill == "blank"):
  558.         temp_potency += 100.0
  559.     if(skill == "head_graze"):
  560.         temp_potency += 100.0
  561.     if(skill == "gauss_round"):
  562.         temp_potency += 180.0
  563.     if(skill == "ricochet"):
  564.         temp_potency += 300.0
  565.    
  566.     if(skill != "auto"):
  567.         temp_damage = ((temp_potency/100)*(WD/25+1)*(TEMP_DEX/9*1.2)*(DET/7290+1)*potency_mod)-1.5
  568.  
  569.     #add skill to list
  570.     #if(skill != "auto"):
  571.     list_of_skills.append(skill + " - " + str(temp_damage))
  572.  
  573.     if(wildfire > 0):
  574.         wildfire_damage += temp_damage
  575.     total_damage += temp_damage
  576.    
  577. #perform rotation
  578. while(how_many_sims > 0):
  579.     rotations(parse_time)
  580.     how_many_sims -= 1
  581.     random.seed(how_many_sims)
  582.    
  583.     #reset all the variables
  584.     slug_shot = False
  585.     clean_shot = False
  586.    
  587.     blood_for_blood_cd = 900
  588.     raging_strikes_cd = 1800
  589.     hypercharge_cd = 1200
  590.     hawks_eye_cd = 900
  591.     rapid_fire_cd = 900
  592.     wildfire_cd = 900
  593.     reassemble_cd = 600
  594.     potion_cd = 2700
  595.  
  596.     ricochet = 600
  597.     blank = 300
  598.     head_graze = 250
  599.     gauss_round = 200
  600.     remover = 0
  601.     hot_shot = 300
  602.     lead_shot = 0
  603.     lead_shot_cd = 300
  604.  
  605.     m_reload = 600
  606.     quick_reload = 300
  607.  
  608.     rapid_fire_count = 0
  609.  
  610.     t_gcd = gcd
  611.     c_gcd = 0
  612.     o_gcd = 0
  613.  
  614.     turret_potency = 80.0
  615.     total_damage = 0.0
  616.    
  617.     list_of_skills = []
  618.     gauss_barrel = False
  619.     reassemble = False
  620.  
  621.     blood_for_blood = 0
  622.     raging_strikes = 0
  623.     hypercharge = 0
  624.     hawks_eye = 0
  625.     rapid_fire = 0
  626.     wildfire = 0
  627.     potion = 0
  628.     reassemble = False
  629.  
  630.     aa = 0
  631.     wildfire_damage = 0.0
  632.  
  633. if(how_many_sims == 0):
  634.     print "The average DPS was: " + str(sum(list_of_results) / len(list_of_results))
  635.     print "The lowest DPS was: " + str(min(list_of_results))
  636.     print "The highest DPS was: " + str(max(list_of_results))
  637.     print "The DPS variance was: "  + str((max(list_of_results) - min(list_of_results)) / (sum(list_of_results) / len(list_of_results)) * 100) + "%."
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement