From 4124cd55f3c8d0d737f1bdcc14cb011dffa8a989 Mon Sep 17 00:00:00 2001 From: Andrew Tomaka Date: Tue, 5 Mar 2013 00:22:17 -0500 Subject: [PATCH] Abstract Stats Collection Abstract the stats collection portions of DPClass so that additional providers might easily be substituted in the future. Initial abstract is weak and can expand when an additional provider is actually found. --- d3hog_driver.php | 18 ++-- libs/barbarian.php | 8 +- libs/demonhunter.php | 32 +++--- libs/diabloclass.php | 88 +++++++++++++++++ libs/diabloprogress_stats.php | 90 +++++++++++++++++ libs/dpclass.php | 177 ---------------------------------- libs/stats.php | 63 ++++++++++++ stats_test.php | 9 ++ 8 files changed, 285 insertions(+), 200 deletions(-) create mode 100644 libs/diabloclass.php create mode 100644 libs/diabloprogress_stats.php delete mode 100644 libs/dpclass.php create mode 100644 libs/stats.php create mode 100644 stats_test.php diff --git a/d3hog_driver.php b/d3hog_driver.php index 111f82a..4103e9d 100644 --- a/d3hog_driver.php +++ b/d3hog_driver.php @@ -1,6 +1,7 @@
Example: http://www.diabloprogress.com/hero/celanian-1548/HsuMing/21706367'); } - $curl = curl_init(); - curl_setopt($curl, CURLOPT_URL, $diabloProgressUrl); - curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); - curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); - $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); - $contents = curl_exec($curl); - curl_close($curl); - $character = DPClassFactory::createClassObject($contents); + $stats = StatsFactory::createStatsObject($diabloProgressUrl); + + if($stats === FALSE) { + die('Bad provider. Either your provider could not be detected or we do not support your provider at this time.'); + } + + $character = DiabloClassFactory::createClassObject($stats->class, $stats); if($character === FALSE) { die('Bad class. Either your class could not be detected or we do not support your class at this time.'); diff --git a/libs/barbarian.php b/libs/barbarian.php index 829d91b..c146ff4 100644 --- a/libs/barbarian.php +++ b/libs/barbarian.php @@ -1,2 +1,8 @@ class = $stats->class; + + parent::__construct($stats); + } +} \ No newline at end of file diff --git a/libs/demonhunter.php b/libs/demonhunter.php index c06356a..5d67d25 100644 --- a/libs/demonhunter.php +++ b/libs/demonhunter.php @@ -1,7 +1,13 @@ class = $stats->class; + + parent::__construct($stats); + } + function EHPScore() { - $ehp = $this->getStat('EHP Unbuffed'); + $ehp = $this->stats->getStat('EHP Unbuffed'); if($ehp <= 500000) { return $ehp / 10000; @@ -15,20 +21,20 @@ class DemonHunter extends DPClass { } function sustainScore() { - $effectiveLs = $this->getStat('DPS Unbuffed') * - $this->getStat('Life Steal') * .2; - $mitigation = $this->getStat('EHP Unbuffed') / $this->getStat('Life'); + $effectiveLs = $this->stats->getStat('DPS Unbuffed') * + $this->stats->getStat('Life Steal') * .2; + $mitigation = $this->stats->getStat('EHP Unbuffed') / $this->stats->getStat('Life'); - return 1 + $mitigation * ($this->getStat('Life on Hit') * - ($this->getStat('Attacks per Second') + 1) / 2 + - $this->getStat('Life per Second') + $effectiveLs) / - ($this->getStat('Life') * $this->EHPScore() * 10000 / - $this->getStat('EHP Unbuffed')); + return 1 + $mitigation * ($this->stats->getStat('Life on Hit') * + ($this->stats->getStat('Attacks per Second') + 1) / 2 + + $this->stats->getStat('Life per Second') + $effectiveLs) / + ($this->stats->getStat('Life') * $this->EHPScore() * 10000 / + $this->stats->getStat('EHP Unbuffed')); } function miscScore() { - return 1 + ($this->getStat('+Maximum Discipline') / 2 + - $this->getStat('+Hatred Regenerated per Second') * 2 + - $this->getStat('+Discipline Regenerated per Second') * 15) / 100; + return 1 + ($this->stats->getStat('+Maximum Discipline') / 2 + + $this->stats->getStat('+Hatred Regenerated per Second') * 2 + + $this->stats->getStat('+Discipline Regenerated per Second') * 15) / 100; } } \ No newline at end of file diff --git a/libs/diabloclass.php b/libs/diabloclass.php new file mode 100644 index 0000000..c08b2ac --- /dev/null +++ b/libs/diabloclass.php @@ -0,0 +1,88 @@ +stats = $stats; + } + + function hallScore() { + return $this->DPSScore() * $this->EHPScore() * $this->sustainScore() + * $this->moveScore() * $this->paragonScore() * $this->miscScore(); + } + + function DPSScore() { + return $this->stats->getStat('DPS Unbuffed') / 1000; + } + + function EHPScore() { + $ehp = $this->stats->getStat('EHP Unbuffed'); + + if($ehp < 1000000) { + return $ehp / 10000; + } elseif(1000000 <= $ehp && $ehp <= 2000000) { + return 100 + ($ehp - 1000000) / 20000; + } elseif(2000000 <= $ehp && $ehp <= 5000000) { + return 150 + ($ehp - 2000000) / 40000; + } elseif($ehp >= 5000000) { + return 225 + ($ehp - 5000000) / 100000; + } + } + + function sustainScore() { + $effectiveLS = $this->stats->getStat('DPS Unbuffed') * + $this->stats->getStat('Life Steal') * .5; + $mitigation = $this->stats->getStat('EHP Unbuffed') / $this->stats->getStat('Life'); + + $rawSustainScore = 1 + $mitigation * ($this->stats->getStat('Life on Hit') * + (1 + ($this->stats->getStat('Attacks per Second') - 1) / 2) + + $effectiveLS + $this->stats->getStat('Life per Second')) / + ($this->stats->getStat('Life') * $this->EHPScore() * 10000 / + $this->stats->getStat('EHP Unbuffed')); + + if($rawSustainScore <= 1.5) { + return $rawSustainScore; + } elseif(1.5 < $rawSustainScore && $rawSustainScore <= 2) { + return 1.5 + ($rawSustainScore - 1.5) / 2; + } elseif(2 < $rawSustainScore && $rawSustainScore <= 3) { + return 1.75 + ($rawSustainScore - 2) / 4; + } else { + return 2 + ($rawSustainScore - 3) / 10; + } + } + + function moveScore() { + return ($this->stats->getStat('Movement Speed') > .25) ? 1.25 : 1 + $this->stats->getStat('Movement Speed'); + } + + function paragonScore() { + return 1 + $this->stats->getStat('Paragon Level') / 2 / 100; + } + + function miscScore() { + return 1; + } +} diff --git a/libs/diabloprogress_stats.php b/libs/diabloprogress_stats.php new file mode 100644 index 0000000..0c4479c --- /dev/null +++ b/libs/diabloprogress_stats.php @@ -0,0 +1,90 @@ +class = $this->findClass(); + $this->parseStats(); + } + + protected + function isParagonMaxed() { + return $this->getStat('Paragon Level') == 100; + } + + private + function findClass() { + preg_match('{(.*?)}', $this->html, $class); + + return str_replace(' ', '', strtolower($class[1])); + } + + function parseStats() { + preg_match_all('{
(.*?):<\/span> (.*?)<\/span><\/nobr><\/div>}', $this->html, $attributes); + + for($i = 0; $i < count($attributes[0]); $i++) { + $attributes[2][$i] = str_replace(',', '', $attributes[2][$i]); + if(preg_match('/%/', $attributes[2][$i]) > 0) { + $attributes[2][$i] = str_replace('%', '', $attributes[2][$i]); + $attributes[2][$i] /= 100; + } + $this->stats[$attributes[1][$i]] = $attributes[2][$i]; + } + + $this->stats['Gem Life'] = $this->calculateGemLife(); + $this->modifyExpBonus(); + + $this->stats['All Elemental Damage'] = $this->elementalDamage(); + + $this->modifyDPSUnbuffed(); + $this->modifyEHP(); + $this->modifyHP(); + } + + function elementalDamage() { + $totalElemental = 0; + foreach($this->stats as $stat => $value) { + if(preg_match('/\+DPS \(.*\)/', $stat) > 0) { + $totalElemental += $value; + } + } + + return ($totalElemental > 0) ? $totalElemental : 0; + } + + function calculateGemLife() { + if($this->isParagonMaxed()) return 0; + + switch($this->getStat('Exp Bonus')) { + case .19: return .12; + case .21: return .14; + case .25: return .15; + case .27: return .16; + case .29: return .17; + case .31: return .18; + default: return 0; + } + } + + function modifyExpBonus() { + if($this->getStat('Exp Bonus') >= .35) { + $this->stats['Exp Bonus'] = $this->getStat('Exp Bonus') - .35; + } + } + + function modifyDPSUnbuffed() { + $this->stats['DPS Unbuffed'] = $this->getStat('DPS Unbuffed') * + max(1, 1 + ($this->getStat('+DPS Against Elites') / 2)); + } + + function modifyEHP() { + $this->stats['EHP Unbuffed'] = $this->getStat('EHP Unbuffed') * + (1 + $this->getStat('Life Bonus') + $this->getStat('Gem Life')) / + (1 + $this->getStat('Life Bonus')); + } + + function modifyHP() { + $this->stats['Life'] = $this->getStat('Life') * + (1 + $this->getStat('Life Bonus') + $this->getStat('Gem Life')) / + (1 + $this->getStat('Life Bonus')); + } +} \ No newline at end of file diff --git a/libs/dpclass.php b/libs/dpclass.php deleted file mode 100644 index d703f55..0000000 --- a/libs/dpclass.php +++ /dev/null @@ -1,177 +0,0 @@ -(.*?)}', $characterPage, $class); - - return str_replace(' ', '', strtolower($class[1])); - } -} - -class DPClass { - var $dpHTML; - var $class; - var $stats = array(); - var $items = array(); - - function __construct($characterPage) { - $this->dpHTML = $characterPage; - - $this->class = get_class($this); - - $this->parseStats(); - } - - function hallScore() { - return $this->DPSScore() * $this->EHPScore() * $this->sustainScore() - * $this->moveScore() * $this->paragonScore() * $this->miscScore(); - } - - function DPSScore() { - return $this->getStat('DPS Unbuffed') / 1000; - } - - function EHPScore() { - $ehp = $this->getStat('EHP Unbuffed'); - - if($ehp < 1000000) { - return $ehp / 10000; - } elseif(1000000 <= $ehp && $ehp <= 2000000) { - return 100 + ($ehp - 1000000) / 20000; - } elseif(2000000 <= $ehp && $ehp <= 5000000) { - return 150 + ($ehp - 2000000) / 40000; - } elseif($ehp >= 5000000) { - return 225 + ($ehp - 5000000) / 100000; - } - } - - function sustainScore() { - $effectiveLS = $this->getStat('DPS Unbuffed') * - $this->getStat('Life Steal') * .5; - $mitigation = $this->getStat('EHP Unbuffed') / $this->getStat('Life'); - - $rawSustainScore = 1 + $mitigation * ($this->getStat('Life on Hit') * - (1 + ($this->getStat('Attacks per Second') - 1) / 2) + - $effectiveLS + $this->getStat('Life per Second')) / - ($this->getStat('Life') * $this->EHPScore() * 10000 / - $this->getStat('EHP Unbuffed')); - - if($rawSustainScore <= 1.5) { - return $rawSustainScore; - } elseif(1.5 < $rawSustainScore && $rawSustainScore <= 2) { - return 1.5 + ($rawSustainScore - 1.5) / 2; - } elseif(2 < $rawSustainScore && $rawSustainScore <= 3) { - return 1.75 + ($rawSustainScore - 2) / 4; - } else { - return 2 + ($rawSustainScore - 3) / 10; - } - } - - function moveScore() { - return ($this->getStat('Movement Speed') > .25) ? 1.25 : 1 + $this->getStat('Movement Speed'); - } - - function paragonScore() { - return 1 + $this->stats['Paragon Level'] / 2 / 100; - } - - function miscScore() { - return 1; - } - - protected - function isParagonMaxed() { - return $this->getStat('Paragon Level') == 100; - } - - function getStat($name) { - return (isset($this->stats[$name])) ? $this->stats[$name] : 0; - } - - private - function parseStats() { - preg_match_all('{
(.*?):<\/span> (.*?)<\/span><\/nobr><\/div>}', $this->dpHTML, $attributes); - - for($i = 0; $i < count($attributes[0]); $i++) { - $attributes[2][$i] = str_replace(',', '', $attributes[2][$i]); - if(preg_match('/%/', $attributes[2][$i]) > 0) { - $attributes[2][$i] = str_replace('%', '', $attributes[2][$i]); - $attributes[2][$i] /= 100; - } - $this->stats[$attributes[1][$i]] = $attributes[2][$i]; - } - - $this->stats['Gem Life'] = $this->calculateGemLife(); - $this->modifyExpBonus(); - - $this->stats['All Elemental Damage'] = $this->elementalDamage(); - - $this->modifyDPSUnbuffed(); - $this->modifyEHP(); - $this->modifyHP(); - } - - function elementalDamage() { - $totalElemental = 0; - foreach($this->stats as $stat => $value) { - if(preg_match('/\+DPS \(.*\)/', $stat) > 0) { - $totalElemental += $value; - } - } - - return ($totalElemental > 0) ? $totalElemental : 0; - } - - function calculateGemLife() { - if($this->isParagonMaxed()) return 0; - - switch($this->getStat('Exp Bonus')) { - case .19: return .12; - case .21: return .14; - case .25: return .15; - case .27: return .16; - case .29: return .17; - case .31: return .18; - default: return 0; - } - } - - function modifyExpBonus() { - if($this->getStat('Exp Bonus') >= .35) { - $this->stats['Exp Bonus'] = $this->getStat('Exp Bonus') - .35; - } - } - - function modifyDPSUnbuffed() { - $this->stats['DPS Unbuffed'] = $this->getStat('DPS Unbuffed') * - max(1, 1 + ($this->getStat('+DPS Against Elites') / 2)); - } - - function modifyEHP() { - $this->stats['EHP Unbuffed'] = $this->getStat('EHP Unbuffed') * - (1 + $this->getStat('Life Bonus') + $this->getStat('Gem Life')) / - (1 + $this->getStat('Life Bonus')); - } - - function modifyHP() { - $this->stats['Life'] = $this->getStat('Life') * - (1 + $this->getStat('Life Bonus') + $this->getStat('Gem Life')) / - (1 + $this->getStat('Life Bonus')); - } -} diff --git a/libs/stats.php b/libs/stats.php new file mode 100644 index 0000000..d6027d4 --- /dev/null +++ b/libs/stats.php @@ -0,0 +1,63 @@ +url = $characterPageUrl; + $this->html = $this->getPageContents(); + + $this->parse(); + } + + function getStat($name) { + return (isset($this->stats[$name])) ? $this->stats[$name] : 0; + } + + private + function getPageContents() { + $curl = curl_init(); + curl_setopt($curl, CURLOPT_URL, $this->url); + curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); + curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); + $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE); + $contents = curl_exec($curl); + curl_close($curl); + + //handle httpCodes and other failures + + return $contents; + } +} diff --git a/stats_test.php b/stats_test.php new file mode 100644 index 0000000..9a9f8ad --- /dev/null +++ b/stats_test.php @@ -0,0 +1,9 @@ +class); + echo "\n\n"; + print_r($stats->stats); + echo "\n\n"; \ No newline at end of file