Porting some code from Javascript i'm having this incovenience. For example:
In javascript we can produce this code.
var a, x, y;
var r = 10;
with (Math) {
a = PI * r * r;
x = r * cos(PI);
y = r * sin(PI / 2);
}
Instead
a = Math.PI * r * r;
x = r * Math.cos(Math.PI);
y = r * Math.sin(Math.PI / 2);
In this last example will be the same comportament in PHP, IE, in second code example Math is redundant.
Someone have any solution for a clear an elegant code?
I'm adding the following code as new example:
class MyExampleClass {
function example {
for($i = 0; $i < count($this->Registers); $i++) {
$r = "50";
$r .= $this->ZeroFill($this->numericOnly($this->Registers[$i]->Id)), 15) . $this->ZeroFill($this->numericOnly($this->Registers[$i]->Inscription), 25);
$r .= $this->ZeroFill($this->Registers[$i]->Model, 2 );
$r .= $this->PadR($this->alpha($this->Registers[$i]->Date), 10 );
$this->WriteRecord( $r);
}
}
In third example I can use a temp $var inside for statement for $this->Registers[$i], but if all treatment code are became in a class like class Sanitize.
with (Sanitize) {
$r .= ZeroFill(numericOnly($tmp), 15); // are much more clear and using OO
}
I want an way to do an shorter and no repetitive code.
What you are looking for is more akin to java than javascript, in java this qualification is optional and can be left out. The javascript's with statement is half functional as it doesn't even work with assignments.
PHP doesn't have that and you have to explicitly type out $this-> every time.
PHP scopes are very different than Javascript. I suppose the best I could think of is extend a class and using $this-> rather than the class name everywhere - Do you have a use case you could share with us?
pi(), cos(), & sin() are all reserved functions in PHP
<?php
$r = 10;
$a = pi() * $r * $r;
$x = $r * cos(pi());
$y = $r * sin(pi() / 2);
?>
Related
I have an old site created with ASP classic and now I got up the courage to convert it to PHP. Must say I am NOT an expert in neither of this languages.
There is a simple function that is driving me crazy. It uses CLng in a way I never seen before and I can't find a similar method in PHP.
Here is the function in ASP classic:
Function TransferDecode(ByRef Source)
Dim C, I, P, S, K
C = Len(Source) / 2
TransferDecode = ""
For I = 0 to C - 1
P = I * 2 + 1
S = Mid(Source, P, 2)
K = CLng("&H" & S)
TransferDecode = TransferDecode & Chr(K)
Next
End Function
And here is my (uncessefull) attempt to convert to PHP:
function transferDecode($source) {
$r = '';
$c = strlen($source) / 2;
for ($i = 0; $i <= $c - 1; $i++) {
$p = $i * 2 + 1;
$s = substr($source, $p, 2);
$k = '&H'.$s;
$r .= chr((int)$k);
}
return $r;
}
Please, can someone explain me what "CLng("&H" & S)" do? Is there a similar CLng method in PHP?
Thank you!
I'd try something like that:
$r .= chr(intval($s, 16));
note: variable $k is not used at all
also, strings in vbscript are 1-based, while in php are 0-based, so $p should be calculated as $p = $i * 2;
I have 5 different variables that I need to calculate. Right now these work, but what I want to do is have the price recalculate every 50 increase. Now, I can code into the form to only allow a maximum purchase of 50 at a time, but I want to allow for as many of each as the person has money for (that is what the numbers are). So I think what I need is a parabola style formula that auto increases every 50, but I don't know exactly what I'm looking for or how to implement it.
$resprice = 20000+($cityFetch['residential']*502)+($cityNum*1000);
$comprice = 18000+($cityFetch['commercial']*506)+($cityNum*1000);
$indprice = 23000+($cityFetch['industrial']*508)+($cityNum*1000);
$landprice = 600+($cityFetch['land']*.008);
$milprice = 25000+($cityFetch['military']*512)+($cityNum*1000);
EDIT: I was indicated that a loop will work for this.
EDIT3: Finally landed on this, Havvy helped me out on IRC
$cityCheck = mysql_query("SELECT * FROM cities WHERE nation='$nation'");
$cityNum = mysql_num_rows($cityCheck);
function determinePrice($baseCost, $scalar, $current, $bought) {
$min = $baseCost + $scalar * ($current + 1) + ($cityNum * 1000);
$max = $baseCost + $scalar * ($current + $bought) + ($cityNum * 1000);
$average = ($min + $max) / 2;
return $average * $bought;
}
$resprice = determinePrice(20000, 502, $cityFetch['residential'], $cityFetch['residential']);
$comprice = determinePrice(18000, 506, $cityFetch['commercial'], $cityFetch['commercial']);
$indprice = determinePrice(23000, 508, $cityFetch['industrial'], $cityFetch['industrial']);
$milprice = determinePrice(25000, 502, $cityFetch['residential'], $cityFetch['military']);
$landprice = 600+($cityFetch['land']*.008);
I use a step size of 1, instead of 50. It's more logical (one less magic number) to not give discounts based on how much you buy at a time, and it would be confusing to new players having a stepwise-linear function.
The reasoning behind this function can be found at http://betterexplained.com/articles/techniques-for-adding-the-numbers-1-to-100/.
function determinePrice($baseCost, $scalar, $current, $bought) {
$min = $scalar * ($current + 1) + ($cityNum * 1000);
$max = $scalar * ($current + $bought) + ($cityNum * 1000);
$average = ($min + $max) / 2;
return $average * $bought;
}
Using it would look something like this:
$resprice = determinePrice(20000, 502, $cityFetch['residential'], $resBought);
It won't work for land though, because land doesn't include the city price in it. For land, you can copy the function and remove the $cityNum * 1000 portions. You could also add in a $isLand parameter to the signature, and use a ternary operator to add 0 instead.
If you don't like that $cityNum has to already be declared with the proper value before declaring this function, you can always add it to the function signature, making it a pure function.
$count=1
if($count==50)
{
You increase the prices then
$count=1;
}
$resprice = 20000+($cityFetch['residential']*502)+($cityNum*1000);
$comprice = 18000+($cityFetch['commercial']*506)+($cityNum*1000);
$indprice = 23000+($cityFetch['industrial']*508)+($cityNum*1000);
$landprice = 600+($cityFetch['land']*.008);
$milprice = 25000+($cityFetch['military']*512)+($cityNum*1000);
$count++;
I've been attempting to implement Vincenty's formulae with the following:
/* Implemented using Vincenty's formulae from http://en.wikipedia.org/wiki/Vincenty%27s_formulae,
* answers "Direct Problem".
* $latlng is a ('lat'=>x1, 'lng'=>y1) array
* $distance is in miles
* $angle is in degrees
*/
function addDistance($latlng, $distance, $bearing) {
//variables
$bearing = deg2rad($bearing);
$iterations = 20; //avoid too-early termination while avoiding the non-convergant case
//knowns
$f = EARTH_SPHEROID_FLATTENING; //1/298.257223563
$a = EARTH_RADIUS_EQUATOR_MILES; //3963.185 mi
$phi1 = deg2rad($latlng['lat']);
$l1 = deg2rad($latlng['lng']);
$b = (1 - $f) * $a;
//first block
$tanU1 = (1-$f)*tan($phi1);
$U1 = atan($tanU1);
$sigma1 = atan($tanU1 / cos($bearing));
$sinalpha = cos($U1)*sin($bearing);
$cos2alpha = (1 - $sinalpha) * (1 + $sinalpha);
$usquared = $cos2alpha * (($a*$a - $b*$b) / 2);
$A = 1 + ($usquared)/16384 * (4096+$usquared*(-768+$usquared*(320 - 175*$usquared)));
$B = ($usquared / 1024)*(256*$usquared*(-128 + $usquared * (74 - 47*$usquared)));
//the loop - determining our value
$sigma = $distance / ($b * $A);
for($i = 0; $i < $iterations; ++$i) {
$twosigmam = 2*$sigma1 + $sigma;
$delta_sigma = $B * sin($sigma) * (cos($twosigmam)+(1/4)*$B*(cos(-1 + 2*cos(cos($twosigmam))) - (1/6)*$B*cos($twosigmam)*(-3+4*sin(sin($sigma)))*(-3+4*cos(cos($twosigmam)))));
$sigma = $distance / ($b * $A) + $delta_sigma;
}
//second block
$phi2 = atan((sin($U1)*cos($sigma)+cos($U1)*sin($sigma)*cos($bearing)) / ((1-$f) * sqrt(sin($sinalpha) + pow(sin($U1)*sin($sigma) - cos($U1)*cos($sigma)*cos($bearing), 2))));
$lambda = atan((sin($sigma) * sin($bearing)) / (cos($U1)*cos($sigma) - sin($U1)*sin($sigma)*cos($bearing)));
$C = ($f / 16)* $cos2alpha * (4+$f*(4-3*$cos2alpha));
$L = $lambda - (1 - $C) * $f * $sinalpha * ($sigma + $C*sin($sigma)*(cos($twosigmam)+$C*cos($sigma)*(-1+2*cos(cos($twosigmam)))));
$alpha2 = atan($sinalpha / (-sin($U1)*sin($sigma) + cos($U1)*cos($sigma)*cos($bearing)));
//and return our results
return array('lat' => rad2deg($phi2), 'lng' => rad2deg($lambda));
}
var_dump(addDistance(array('lat' => 93.129, 'lng' => -43.221), 20, 135);
The issue is that the results are not reasonable - I'm getting variances of up to 20 latitude and longitude keeping the distance at 20. Is it not in units of elliptical distance on the sphere? Am I misunderstanding something, or is my implementation flawed?
There are a number of errors in transcription from the wikipedia page Direct Problem section:
Your u2 expression has 2 in the denominator where it should have b2;
Your A and B expressions are inconsistent about whether the initial fraction factor needs to be parenthesised to correctly express a / b * c as (a/b) * c - what happens without parentheses is a php syntax issue which I don't know the answer to, but you should favour clarity;
You should be iterating "until there is no significant change in sigma", which may or may not happen in your fixed number of iterations;
There are errors in your DELTA_sigma formula:
on the wikipedia page, the first term inside the square bracket [ is cos sigma (-1 etc, whereas you have cos (-1 etc, which is very different;
in the same formula and also later, note that cos2 x means (cos x)(cos x), not cos cos x!
Your phi_2 formula has a sin($sinalpha) where it should have a sin($sinalpha)*sin($sinalpha);
I think that's all.
Have you tried this:
https://github.com/treffynnon/Geographic-Calculations-in-PHP
I'm looking for a way to generate license keys by a PHP script and then transfer its to my application (Air, AS3), and in this application to read the data correctly. For example, here is the code:
<?php
error_reporting(E_ALL);
function KeyGen(){
$key = md5(mktime());
$new_key = '';
for($i=1; $i <= 25; $i ++ ){
$new_key .= $key[$i];
if ( $i%5==0 && $i != 25) $new_key.='-';
}
return strtoupper($new_key);
}
echo KeyGen();
?>
The generates key about like this: 1AS7-09BD-96A1-CC8D-F106.
I want to add some information into key - e-mail user, then pass it to the client (Air app), decrypt the data and dysplay in app.
Is it possible?
Ok lets break down what you are asking:
You want to:
add some information into key
Well what information do you want to add? Do you want to make the key longer when you do this? Do you want this information to require a key to decrypt? In the vaugest sense thats quite possible with PHP
e-mail user
PHP has a mail() function. It pretty much just works.
then pass it to the client (Air app)
Is the air app invoking this php script via a http request? if so set the content-type and output the key to it.
decrypt the data
Back to point 1, possible, but do you want a key or not, and do you care if the format changes. Also, don't you want to decrypt the data in the AS3 app?
display in app.
If the AS3 app is going to display the key, or the decrypted data, then it is AS3 where you need to get it to display the data.
If you just want to store some information but "encode" it using the set of symbols you used above (0-9A-Z), you can use the algorithm below.
The code is an old Python (3) program of mine. It's certainly not fancy in any way, nor very tested, but I suppose it's better than nothing since you haven't got many answers yet. It should be pretty easy to port the code to PHP or AS. The reduce statements can for example be replaced by imperative style loops. Also note that // denotes integer division in Python.
It should also be pretty easy to slap some compression/encryption onto it. Hope it resembles what you wanted. Here goes.
from functools import reduce
class Coder:
def __init__(self, alphabet=None, groups=4):
if not alphabet:
alphabet = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
self.alphabet = alphabet
self.groups = groups
def encode(self, txt):
N = len(self.alphabet)
num = reduce(lambda x,y: (x*256)+y, map(ord, txt))
# encode to alphabet
a = []
while num > 0:
i = num % N
a.append(self.alphabet[i])
num -= i
num = num//N
c = "".join(a)
if self.groups > 0:
# right zero pad
while len(c) % self.groups != 0:
c = c + self.alphabet[0]
# make groups
return '-'.join([c[x*self.groups:(x+1)*self.groups]
for x in range(len(c)//self.groups)])
return c
def decode(self, txt, separator='-'):
# remove padding zeros and separators
x = txt.rstrip(self.alphabet[0])
if separator != None:
x = x.replace(separator, '')
N = len(self.alphabet)
x = [self.alphabet.find(c) for c in x]
x.reverse()
num = reduce(lambda x,y: (x*N)+y, x)
a = []
while num > 0:
i = num % 256
a.append(i)
num -= i
num = num//256
a.reverse()
return ''.join(map(chr, a))
if __name__ == "__main__":
k = Coder()
s = "Hello world!"
e = k.encode(s)
print("Encoded:", e)
d = k.decode(e)
print("Decoded:", d)
Example output:
Encoded: D1RD-YU0C-5NVG-5XL8-7620
Decoded: Hello world!
with md5 you cannot do this as this is a one-way hash. You should use a decipher method to do so as it uses a key to encode and decode it. There are several php extensions that can do this, consult php manual. You can also use a third party software to this, e.g. http://wwww.phplicengine.com
I found value in Andre's answer using Python.
I, like the question author, needed a php solution so I rewrote Andre's code as PHP. I am posting it here in case anyone else finds it useful.
HOWEVER, there are limitations with this that don't exist in the Python version:
It does not appear to encode any string larger than 8 characters. It may be solvable? It's something to do with how PHP handles very large integers. Thankfully I only need to encode less than 8 characters for my use case. It may work under different environments, I'm not sure. Anyway, with this caveat stated, here is the class:
<?php
/**
* Basic key generator class based on a simple Python solution by André Laszlo.
* It's probably not secure in any way, shape or form. But may be suitable for
* your requirements (as it was for me).
*
* Due to limitations with PHP's processing of large integers, unlike the Python
* app, only a small amount of data can be encoded / decoded. It appears to
* allow a maximum of 8 unencoded characters.
*
* The original Python app is here: https://stackoverflow.com/a/6515005
*/
class KeyGen
{
/**
* #var array
*/
protected $alphabet;
/**
* #var int
*/
protected $groups;
/**
* #var string
*/
protected $separator;
/**
* Controller sets the alphabet and group class properties
*
* #param string $alphabet
* #param int $groups
* #param string $separator
*/
public function __construct(string $alphabet = null, int $groups = 4, string $separator = '-')
{
$alphabet = $alphabet ?: '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ';
$this->alphabet = str_split($alphabet);
$this->groups = $groups;
$this->separator = $separator;
}
/**
* Encodes a string into a typical license key format
*
* #param string $txt
* #return string
*/
public function encode(string $txt)
{
// calculate the magic number
$asciiVals = array_map('ord', str_split($txt));
$num = array_reduce($asciiVals, function($x, $y) {
return ($x * 256) + $y;
});
// encode
$a = [];
$i = 0;
$n = count($this->alphabet);
while ($num > 0) {
$i = $num % $n;
array_push($a, $this->alphabet[$i]);
$num -= $i;
$num = intdiv($num, $n);
}
// add padding digits
$str = implode('', $a);
if($this->groups > 0) {
while (strlen($str) % $this->groups != 0) {
$str .= $this->alphabet[0];
}
}
// split into groups
if($this->groups) {
$split = str_split($str, $this->groups);
$str = implode($this->separator, $split);
}
return $str;
}
/**
* Decodes a license key
*
* #param string $txt
* #return string
*/
public function decode(string $txt)
{
// remove separators and padding
$stripped = str_replace($this->separator, '', $txt);
$stripped = rtrim($stripped, $this->alphabet[0]);
// get array of alphabet positions
$alphabetPosistions = [];
foreach(str_split($stripped) as $char){
array_push($alphabetPosistions, array_search($char, $this->alphabet));
}
// caluculate the magic number
$alphabetPosistions = array_reverse($alphabetPosistions);
$num = array_reduce($alphabetPosistions, function($x, $y) {
$n = count($this->alphabet);
return ($x * $n) + $y;
});
// decode
$a = [];
$i = 0;
$n = count($this->alphabet);
while ($num > 0) {
$i = $num % 256;
array_push($a, $i);
$num -= $i;
$num = intdiv($num, 256);
}
return implode('', array_map('chr', array_reverse($a)));
}
}
And here is an example usage, encoding and decoding "ABC123":
$keyGen = new KeyGen();
$encoded = $keyGen->encode('ABC123'); //returns 3WJU-YSMF-P000
$decoded = $keyGen->decode('3WJU-YSMF-P000'); //returns ABC123
So I've read the two related questions for calculating a trend line for a graph, but I'm still lost.
I have an array of xy coordinates, and I want to come up with another array of xy coordinates (can be fewer coordinates) that represent a logarithmic trend line using PHP.
I'm passing these arrays to javascript to plot graphs on the client side.
Logarithmic Least Squares
Since we can convert a logarithmic function into a line by taking the log of the x values, we can perform a linear least squares curve fitting. In fact, the work has been done for us and a solution is presented at Math World.
In brief, we're given $X and $Y values that are from a distribution like y = a + b * log(x). The least squares method will give some values aFit and bFit that minimize the distance from the parametric curve to the data points given.
Here is an example implementation in PHP:
First I'll generate some random data with known underlying distribution given by $a and $b
// True parameter valaues
$a = 10;
$b = 5;
// Range of x values to generate
$x_min = 1;
$x_max = 10;
$nPoints = 50;
// Generate some random points on y = a * log(x) + b
$X = array();
$Y = array();
for($p = 0; $p < $nPoints; $p++){
$x = $p / $nPoints * ($x_max - $x_min) + $x_min;
$y = $a + $b * log($x);
$X[] = $x + rand(0, 200) / ($nPoints * $x_max);
$Y[] = $y + rand(0, 200) / ($nPoints * $x_max);
}
Now, here's how to use the equations given to estimate $a and $b.
// Now convert to log-scale for X
$logX = array_map('log', $X);
// Now estimate $a and $b using equations from Math World
$n = count($X);
$square = create_function('$x', 'return pow($x,2);');
$x_squared = array_sum(array_map($square, $logX));
$xy = array_sum(array_map(create_function('$x,$y', 'return $x*$y;'), $logX, $Y));
$bFit = ($n * $xy - array_sum($Y) * array_sum($logX)) /
($n * $x_squared - pow(array_sum($logX), 2));
$aFit = (array_sum($Y) - $bFit * array_sum($logX)) / $n;
You may then generate points for your Javascript as densely as you like:
$Yfit = array();
foreach($X as $x) {
$Yfit[] = $aFit + $bFit * log($x);
}
In this case, the code estimates bFit = 5.17 and aFit = 9.7, which is quite close for only 50 data points.
For the example data given in the comment below, a logarithmic function does not fit well.
The least squares solution is y = -514.734835478 + 2180.51562281 * log(x) which is essentially a line in this domain.
I would recommend using library: http://www.drque.net/Projects/PolynomialRegression/
Available by Composer: https://packagist.org/packages/dr-que/polynomial-regression.
In case anyone is having problems with the create_function, here is how I edited it. (Though I wasn't using logs, so I did take those out.)
I also reduced the number of calculations and added an R2. It seems to work so far.
function lsq(){
$X = array(1,2,3,4,5);
$Y = array(.3,.2,.7,.9,.8);
// Now estimate $a and $b using equations from Math World
$n = count($X);
$mult_elem = function($x,$y){ //anon function mult array elements
$output=$x*$y; //will be called on each element
return $output;
};
$sumX2 = array_sum(array_map($mult_elem, $X, $X));
$sumXY = array_sum(array_map($mult_elem, $X, $Y));
$sumY = array_sum($Y);
$sumX = array_sum($X);
$bFit = ($n * $sumXY - $sumY * $sumX) /
($n * $sumX2 - pow($sumX, 2));
$aFit = ($sumY - $bFit * $sumX) / $n;
echo ' intercept ',$aFit,' ';
echo ' slope ',$bFit,' ' ;
//r2
$sumY2 = array_sum(array_map($mult_elem, $Y, $Y));
$top=($n*$sumXY-$sumY*$sumX);
$bottom=($n*$sumX2-$sumX*$sumX)*($n*$sumY2-$sumY*$sumY);
$r2=pow($top/sqrt($bottom),2);
echo ' r2 ',$r2;
}