Created
February 11, 2014 14:17
-
-
Save Grom-S/8935609 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
// Usage example | |
$testsRunner = new TestsRunner(); | |
$testsRunner->setJsonFileLocation('path/to/tests.json'); | |
$values = $testsRunner->getValues(37, 20, 'us'); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[ | |
{ | |
"name": "Example Test", | |
"conditions": { | |
"product_id": "0", | |
"template_id": "0", | |
"country": "us", | |
"query": { | |
"template": "main", | |
"id": "77" | |
} | |
}, | |
"plans": [ | |
{ | |
"ratio": 25, | |
"values": { | |
"installer": "setup.exe", | |
"language": "en" | |
} | |
}, | |
{ | |
"ratio": 40, | |
"values": { | |
"installer": "setup2.exe", | |
"size": "large", | |
"language": "ru" | |
} | |
}, | |
{ | |
"ratio": 35, | |
"values": { | |
"installer": "setup3.exe", | |
"size": "small", | |
"language": "de" | |
} | |
} | |
] | |
}, | |
{ | |
"name": "Another Test", | |
"conditions": { | |
"product_id": "37", | |
"template_id": "21", | |
"country": "ru", | |
"query": null | |
}, | |
"plans": [ | |
{ | |
"ratio": 23, | |
"values": { | |
"param1": "1" | |
} | |
}, | |
{ | |
"ratio": 75, | |
"values": { | |
"param1": "2" | |
} | |
}, | |
{ | |
"ratio": 2, | |
"values": { | |
"param1": "3" | |
} | |
} | |
] | |
} | |
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
class TestsRunner | |
{ | |
private $jsonFilePath; | |
public function setJsonFileLocation($path) | |
{ | |
if (!file_exists($path)) { | |
throw new Exception(sprintf('JSON file "%s" was not found', $path)); | |
} | |
$this->jsonFilePath = $path; | |
} | |
public function getValues($productId, $templateId, $countryCode) | |
{ | |
if (!$productId) { | |
throw new Exception('productId parameter is required'); | |
} | |
if (!$templateId) { | |
throw new Exception('templateId parameter is required'); | |
} | |
if (!$countryCode) { | |
throw new Exception('countryCode parameter is required'); | |
} | |
try { | |
$test = $this->findFirstMatchedTest($productId, $templateId, $countryCode); | |
$winnerPlan = $this->runTest($test); | |
return $winnerPlan['values']; | |
} | |
catch (Exception $e) { | |
return array(); | |
} | |
} | |
private function findFirstMatchedTest($productId, $templateId, $countryCode) | |
{ | |
$tests = $this->getTestsFromFile(); | |
foreach ($tests as $test) { | |
if ($this->matches($test, $productId, $templateId, $countryCode)) { | |
return $test; | |
} | |
} | |
throw new Exception('No tests matched'); | |
} | |
private function getTestsFromFile() | |
{ | |
return json_decode(file_get_contents($this->jsonFilePath), true); | |
} | |
private function runTest($test) | |
{ | |
$value = mt_rand(0, 100); | |
$winnerIndex = 0; | |
$min = 0; | |
foreach ($test['plans'] as $index => $plan) { | |
$planRatio = (int)$plan['ratio']; | |
$max = $min + $planRatio; | |
if ($value >= $min && $value <= $max) { | |
$winnerIndex = $index; | |
break; | |
} | |
$min += $planRatio; | |
} | |
return $test['plans'][$winnerIndex]; | |
} | |
private function matches($test, $productId, $templateId, $countryCode) | |
{ | |
$conditions = $test['conditions']; | |
// if there is product constrain in test | |
if ($conditions['product_id']) { | |
// and product not matches | |
if ($productId != $conditions['product_id']) { | |
return false; | |
} | |
} | |
// if there is template constrain in test | |
if ($conditions['template_id']) { | |
// and template not matches | |
if ($templateId != $conditions['template_id']) { | |
return false; | |
} | |
} | |
// if there is query constrain in the test | |
if ($conditions['query']) { | |
foreach ($conditions['query'] as $paramName => $paramValue) { | |
if (!isset($_GET[$paramName])) { | |
return false; | |
} | |
if ($_GET[$paramName] != $paramValue) { | |
return false; | |
} | |
} | |
} | |
// if there is country constrain in the test | |
if ($conditions['country']) { | |
if (strtolower($countryCode) !== strtolower($conditions['country'])) { | |
return false; | |
} | |
} | |
return true; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment