PHP Regex statements - php

With a post request, I'm trying to return a booking number to my iOS App. It posts the current date as a string which is written to a file on my server.
The logic is, that whenever the date from the last entry does not match the date passed in the post request, the booking number starts from 01. If it is the same date, the booking number gets increased by one.
The text file I write my entries to looks like this:
2017-03-03, 1;
2017-03-03, 2;
2017-03-03, 3;
2017-03-03, 4;
2017-03-03, 5
I am using regex to find the last entry, comparing its date to the current and assigning the new booking number.
Here is my code:
if (preg_match_all("/\d{4}-\d{1,2}-\d{1,2},\s\d\z/", $textFileString, $entryArray)) {
if (preg_match_all("/\d{4}-\d{1,2}-\d{1,2}/", $entryArray[0][0], $dateArray)) {
if ($dateArray[0][0] == $currentDate) { //$currentDate's value comes from the post request
if (preg_match_all("/\d\z/", $entry[0][0], $numberArray)) {
$bookingNumber = $output_array[0][0]+1;
}
} else {
$bookingNumber = 1;
}
}
}
Note: I do successfully write to the file.

I suggest switching to preg_match (since you only need to find a single match) and add capturing groups to the pattern so as to reduce the code a bit:
$textFileString = '2017-03-03, 1;
2017-03-03, 2;
2017-03-03, 3;
2017-03-03, 4;
2017-03-03, 5';
$currentDate = '2017-03-03';
if (preg_match("/(\d{4}-\d{1,2}-\d{1,2}),\s(\d{1,2})\z/", $textFileString, $entryArray)) {
if ($entryArray[1] == $currentDate) { //$currentDate's value comes from the post request
$bookingNumber = $entryArray[2]+1;
} else {
$bookingNumber = 1;
}
}
echo $bookingNumber;
See the PHP demo.
Note you may also replace \z with $ since the $ anchor matches at the end of the string (or before a final LF in the string) by default.
Now, (\d{4}-\d{1,2}-\d{1,2}),\s(\d{1,2})\z contains two capturing groups that you may access via $entryArray[1] and $entryArray[2].

Related

How can you determine remaining space on page with ezpdf?

I'm using rospdf/php-pdf - the middle of the pdf is a table of variable length. I want to make sure there is enough space to print the final section on the page, if not I want to add a new page. I'd like to do something like this but $position has no value. How can I find out the current position?
$position = $pdf->ezSetDy;
if($position < 100){
$pdf->ezNewPage();
}
You can try the following:
$yPos = $pdf->y - $pdf->ez['bottomMargin'];
if ($yPos < 100) {
$pdf->ezNewPage();
}

Decrementing round number and check for results

This is a basic PHP problem and I probably could crack it in no time tomorrow morning, but today it's been a looong day, so...
I have a function that returns neighborhood name using Google Maps API. I noticed that neighborhood name is changing based on a round of the decimals in lon lat. When it cannot return neighborhood name it returns city name instead.
What I am trying to do is start with 12 decimal numbers and compare returned result to the city name and if it's the same, continue decrementing until the returned result is different.
Here's what I've got:
$rnd = 12;
function get_hood($lat, $lon, $rnd) {
$get_API = "http://maps.googleapis.com/maps/api/geocode/json?latlng=";
$get_API .= round($lat,$rnd).",";
$get_API .= round($lon,$rnd);
$jsonfile = file_get_contents($get_API.'&sensor=false');
$jsonarray = json_decode($jsonfile);
if (isset($jsonarray->results[1]->address_components[1]->long_name)) {
return($jsonarray->results[1]->address_components[1]->long_name);
}
}
for($i=1; $i<=$rnd; $i--) {
if ($b->busCity == get_hood($b->lat, $b->lon, $rnd)) {
echo get_hood($b->lat, $b->lon, $rnd);
break;
} else {
echo get_hood($b->lat, $b->lon, $rnd);
}
}
I feel like I'm going in circles and need a fresh look at this.
Thanks.
I see several problems with your for loop. First of all, you need to start your loop with the $rnd and stop at 0 or 1. Second, you don't seem to use the loop variable, but always use the same $rnd variable every time. Lastly, you use $b variable, but it's not defined anywhere (although I think it may be defined outside of the short snippet you included).
If I understand correctly what you want to get, then this code should get you there (note I had to define $b to test the code)
$b = (object)[
'lat' => 51.123456789012,
'lon' => 0.123456789012,
'busCity' => 'Withyham'
];
for($i = $rnd; $i >= 0; $i--) {
$newCity = get_hood($b->lat, $b->lon, $i);
echo "$i => $newCity\n";
if($b->busCity != $newCity) {
break;
}
}

PHP function - output of function is the input of another function

I have the following function where certain inputs are given and then 4 outputs are given: -
function rsiNext($dailyGainAvgPrev, $dailyLossAvgPrev,$cpDailyNext){
if($cpDailyNext > 0){
$dailyGainAvgNext = (($dailyGainAvgPrev * 13) + $cpDailyNext)/14;
}else{
$dailyGainAvgNext = (($dailyGainAvgPrev * 13) + 0)/14;
}
if($cpDailyNext < 0){
$dailyLossAvgNext = (($dailyLossAvgPrev*13) + abs($cpDailyNext))/14;
}else{
$dailyLossAvgNext = (($dailyLossAvgPrev*13) + abs(0))/14;
}
$relStrNext = $dailyGainAvgNext/$dailyLossAvgNext;
if($dailyLossAvgNext == 0){
$relStrIndNext = 100;
}else{
$relStrIndNext = 100-(100/(1+$relStrNext));
}
return array($dailyGainAvgNext, $dailyLossAvgNext, $relStrNext, $relStrIndNext);
}
I output the values using the following line of code:
//Get value for day 15
list($dailyGainAvg02, $dailyLossAvg02, $relStr02, $relStrInd02) = rsiNext($averageGains14, $averageLosses14, $priceDifferences[15]);
echo '<tr><td>'.$dailyGainAvg02.'</td><td>'.$dailyLossAvg02.'</td><td>'.$relStr02.'</td><td>'.$relStrInd02.'</td></tr>';
Now when I want the value for day 16 I use the following line of code:
//Get value for day 16
list($dailyGainAvg03, $dailyLossAvg03, $relStr03, $relStrInd03) = rsiNext($dailyGainAvg02, $dailyLossAvg02, $priceDifferences[16]);
echo '<tr><td>'.$dailyGainAvg03.'</td><td>'.$dailyLossAvg03.'</td><td>'.$relStr03.'</td><td>'.$relStrInd03.'</td></tr>';
The output of day 15 is the input of day 16, the output of day 16 is the input of day 17. The output of day 17 is the input of day 18, etc...
I need to repeat the list for 100 days. How can I go about it without repeating the list line for another 100 days?
Thank you.
Assuming you have the $priceDifferences array fully populated, something like the following should do:
$cur_dailyGainAvg = 0; // you need to initialize this value appropriately
$cur_dailyLossAvg = 0; // you need to initialize this value appropriately
for ($idx = 1; $idx <= 100; $idx++) {
list($new_dailyGainAvg, $new_dailyLossAvg, $new_relStr, $new_relStrInd) = rsiNext($cur_dailyGainAvg, $cur_dailyLossAvg, $priceDifferences[$idx])
// print
echo '<tr><td>'.$new_dailyGainAvg.'</td><td>'.$new_dailyLossAvg.'</td><td>'.$new_relStr.'</td><td>'.$new_relStrInd.'</td></tr>';
// shift the new values onto the current, and repeat the calculation
$cur_dailyGainAvg = $new_dailyGainAvg;
$cur_dailyLossAvg = $new_dailyLossAvg;
}
Basically distinguish between your "current" values, which you feed into your function, and the "new" values that come out, then "shift" the new onto the current ones and repeat.
You may have to check the boundaries of the loop.

Insert random letters and letters of string in a table just like in wordsearch

this codes is for displaying random letters with a table like in a word search game. The problem is,.I can't insert strings in the table,. what if I have array of strings,. eg., sample, them, power, some. How can I insert these strings in the cell?
I am creating something like this http://children.pfcblogs.com/learn/word-search-test/
$row = 10;
$col = 10;
$w = 8;
$h = 8;
for ($r=1;$r<=$row;$r++) {
for ($c=1;$c<=$col;$c++) {
$pdf->Cell($w,$h,$str= array_merge(range('A','Z'))[mt_rand(1,24)],1,0,'C');
}
$pdf->Ln($h);
}
This is way above and beyond for stackoverflow, but I'm in a good mood. :-)
So this takes a string of words (you can add more) separated by comas and splits those in to an array and then finds words that will fit until it gets down to 1 letter then it just uses the random letters from before to fill the space.
This is far from perfect one thing you'd see is all of the lines will start with words and end with random letters. Also, the words are only horizontal not vertical. Building matrixes of words horizontal, vertical, and diagonal gets pretty complex and is certainly beyond the scope of this site.
Here is the code as it stands. It's a good start.
$row = 10;
$col = 10;
$w = 8;
$h = 8;
$characters = range('A','Z');
$words="in, on, it, up, at, am, of, and, band, banned, bland, brand, brande, canned, chand, fanned, gland, grand, grande, hand, land, lande, mande, manned, panned, planned, rand, sande, scanned, shand, spanned, stand, strand, strande, tanned, vande, zand";
$wordList = explode(",",$words);
$myWord="";
$max = count($characters) - 1;
for ($r=1;$r<=$row;$r++) {
for ($c=1;$c<=$col;$c++) {
//if we have more than 1 space
//(enough room for a 2 or more letter word)
$maxWordLength=$col-$c+1;
if($maxWordLength > 1){
//get a word if we need a new one
if(empty($myWord)){
$wordLen=99;
while($wordLen > $maxWordLength){
$myWord=trim(strToUpper($wordList[mt_rand(0,count($wordList))]));
$wordLen=strlen($myWord);
}
}
//get the next letter of the word we're using
$thisChar=substr($myWord,0,1);
$myWord=substr($myWord,1);
}else{
//if we don't have room for a word put a random letter
$thisChar=$characters[mt_rand(0,$max)];
}
$pdf->Cell($w,$h,$thisChar,1,0,'C');
//for debugging (remove this)
echo($thisChar.' ');
}
$pdf->Ln($h);
//for debugging remove this
echo('<hr>');
}
Also, here is a link to an existing open source PHP solution that is along the lines of what you're looking for. I downloaded it and took a peek and it's about 3000 lines of code. So as I said well beyond the scope of stack overflow.
http://fswordfinder.sourceforge.net/
Try this code...
$row = 10;
$col = 10;
$w = 8;
$h = 8;
$characters = range('A','Z');
$max = count($characters) - 1;
for ($r=1;$r<=$row;$r++) {
for ($c=1;$c<=$col;$c++) {
$pdf->Cell($w,$h,$characters[mt_rand(0,$max)],1,0,'C');
//for debugging (remove this)
echo("$w,$h,{$characters[mt_rand(0,$max)]},1,0,'C'");
echo('<br>');
}
$pdf->Ln($h);
}
I added in the echo code to see what it's doing since I don't have the PDF library that you are using so I couldn't test that but the echo output was like this so assuming the pdf cell method is set up correctly it should work.
8,8,D,1,0,'C'
8,8,S,1,0,'C'
8,8,C,1,0,'C'
8,8,C,1,0,'C'
8,8,F,1,0,'C'
8,8,Q,1,0,'C'
8,8,B,1,0,'C'
8,8,H,1,0,'C'
8,8,C,1,0,'C'
8,8,N,1,0,'C'
8,8,A,1,0,'C'
8,8,H,1,0,'C'
8,8,Y,1,0,'C'
8,8,T,1,0,'C'
8,8,B,1,0,'C'
8,8,V,1,0,'C'
8,8,Y,1,0,'C'
...

do-while in php resulting a non-stop page loading

I want to have a $startdate counting 3 days backward from an input date by user, where those 3 days are not holidays.
So if the input date by user is October 22, the $startdate would be October 17 instead of October 19. Because October 19 and 20 are holidays
$i = 1;
do{
//some code to produce the $startdate
//...
//end
//check if $startdate is holiday or not
$this->db->where('hl_date',$startdate);
$query = $this->db->get('php_ms_holiday');
//if $startdate = holiday, it doesn't count
if($query->result_array()){
}
else{
$i++;
}
}while($i <= 3);
But, with that code I have a non-stop loading on the browser when a $startdate captured inside the if($query->result_array()) statement. And the browser can only returning results when I put something like this code below, inside the if($query->result_array()) statement:
$i = $i + n; //n is a number starting from 1, or
$i++;
but not:
$i = $i; //or
$i = $i + 0;
Why is that?
You just make a DB query which result interprets as TRUE. Maybe I wrong but it seems you are make the same db query in each loop iteration.
So, check your query, for example add specific date for holiday checking.
if($query->result_array()) will always evaluate to true, if your query is correctly formulated. So also if the number of rows returned is 0. This means that you never ever go to the else. You if-statement should check the number of results returned instead; Furthermore, I personally would prefer a normal for-loop:
for($i = 0; $i < 3)
{
//some code to produce the $startdate
//...
//end
//check if $startdate is holiday or not
$this->db->where('hl_date',$startdate);
$query = $this->db->get('php_ms_holiday');
//if $startdate = holiday, it doesn't count
if [num_rows equals 0] // test num_rows here; Not sure what your class offers here
{
$i++; // increment counter
// do whatever else you want to do
}
}
If this is always true:
if($query->result_array()){
}
Then this will always be true:
}while($i <= 3); //$i is never adjusted, so it will always be less than 3
Since you say that you want to display data from with the last 3 days but if there are holidays in between, you don't want to count them. To get around this I think you should not use the literal "3" since it can be adjusted, it should be a variable too.
A possible solution would be to have a variable such as:
$days_back = 3;
Then try to count the amount of holidays within the last 3 days(or something like that):
//You can make the holidays to be zero by default
$holidays = someWayToCountHolidays($startDate, $endDate); //You'll obviously have to code this
Then you can make make the variable your while loop will work agains
$num_days = $days_back + $holidays; //$holidays can be zero by default
Then something like below for you do while loop:
if($query->result_array()){
//Then do what ever you want to do here
} else {
//Then do what ever you want to do here
}
$i++; //Adjust $i
}while($i <= $num_days);

Categories