Skip to content

Instantly share code, notes, and snippets.

@elzekool
Last active August 29, 2015 14:13
Show Gist options
  • Save elzekool/12303b819476b4f70249 to your computer and use it in GitHub Desktop.
Save elzekool/12303b819476b4f70249 to your computer and use it in GitHub Desktop.
Make an commercial price of original price with margin
<?php
/**
* Make nice commercial price from orignal price
*
* @param string $price Original price
* @param string $rangeDown Range down in percent
* @param string $rangeUp Range up in percent
* @param string $minUnit Minimal unit to increment up/down
*
* @return string Commercial price
**/
function commercialize($price, $rangeDown = '10', $rangeUp = '0', $minUnit = '1.00')
{
// Make price universal format, with two decimals
// this allows str_replace later on
$price = bcmul($price, '1.00', 2);
// First determine upper and lower boundaries
$minPrice = bcsub($price, bcmul($price, bcdiv($rangeDown, '100', 3), 2));
$maxPrice = bcadd($price, bcmul($price, bcdiv($rangeUp, '100', 3), 2));
// Prices found in range
$prices = [];
// Go trough multiplication factors
for($x = 9; $x >= 2; $x--) {
// Base is used to substract one or add one to the current number to test
$base = bcmul('1.00', bcmul($minUnit, bcpow('10.00', $x, 2)), 2);
// Replace is used to replace everything after the base with 99
$replace = bcmul(preg_replace('/0/', '9', str_replace('1', '', $base), $x), '1.00', 2);
// Make sure auto added 0. is correctly handled
if (strpos($replace, '0.') === 0) {
$replace = substr($replace, 1);
}
// Create prices to test
$testPrices = [
$price,
bcsub($price, $base, 2),
bcadd($price, $base, 2)
];
// Test prices, and store them if the fall in range
foreach($testPrices as $testPrice) {
$testPrice = substr($testPrice, 0, strlen($testPrice) - strlen($replace)) . $replace;
if (bccomp($testPrice, $maxPrice, 2) > 0) { continue; }
if (bccomp($minPrice, $testPrice, 2) > 0) { continue; }
$prices[] = $testPrice;
}
}
// If no prices are found, just return the original
if (count($prices) == 0) { return $price; }
// Now test which price has the lowest difference with the
// original value
$diff = str_replace('-', '', bcsub($price, $prices[0], 2));
$out = $prices[0];
foreach($prices as $n_price) {
$n_diff = str_replace('-', '', bcsub($price, $n_price, 2));
if (bccomp($diff, $n_diff, 2) > 0) {
$diff = $n_diff;
$out = $n_price;
}
}
return $out;
}
header("Content-type: text/plain");
$tests = [
[ '12.21', '25', '25', '0.01' ],
[ '1518', '25', '25', '1.00' ],
[ '1684', '25', '25', '1.00' ],
[ '7193', '25', '25', '1.00' ],
[ '8018', '25', '25', '1.00' ],
[ '8.21', '25', '25', '0.01' ],
[ '21.50', '25', '25', '0.01' ],
];
foreach($tests as $test) {
list($price, $minRange, $maxRange, $minUnit) = $test;
$commercial = commercialize($price, $minRange, $maxRange, $minUnit);
echo sprintf('%s --> %s', str_pad($price, 8, ' '), $commercial) . "\n";
}
// OUTPUT:
// 12.21 --> 11.99
// 1518 --> 1499.00
// 1684 --> 1699.00
// 7193 --> 7199.00
// 8018 --> 7999.00
// 8.21 --> 7.99
// 21.50 --> 21.99
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment