Paging through api - PHP - php

I am trying to construct a php script that will page through an API. The api return ~25197 XML records. I am able to pass a start_offset and a end_offset to the API which will return a subset of the results.
The challenge I am having is that the for loop is not capturing the remaining records that are not within the 1000.
Example, the current for loop processes the records in blocks of 1000 (0-1000,1001-2000,2001-3000, etc.) I am not able to get the final block - 25,000 to 26,000. The for loop stop processing at 24,000 - 25,000. This leaves me with 197 unprocessed XML results.
<?php
//Set Start and Offset Parameters
$start_offset = 0;
$end_offset = 0;
$items_per_page = 1000;
$number = 0;
$counter = -2;
for ($count=0; $count<=100; $count++) {
$counter++;
//Validate that the counter is not null
if ($number != null){
echo "\n";
echo file_get_contents($static_url . "/sc_vuln_query-compliance.php?start=$start_offset&end=$end_offset&seq=$counter");
}
//Initialize the start and end offset variables
$end_offset = $number+=$items_per_page;
$start_offset = $number-$items_per_page+1;
//We want to start at record 0, reset start_offset back to 0 instead of 1
if($start_offset == 1) {
$start_offset = $number-$items_per_page;
}
// We are at the end of the total records, display the remaining
if ($number>$total_xml_records) {
$counter = $counter+1;
$padding = $end_offset + $items_per_page;
echo "\n";
echo file_get_contents($static_url. "/sc_vuln_query-compliance.php?start=$start_offset&end=$padding&seq=$counter");
break;
}
}
?>

Your code is at least buggy at this line $padding = $end_offset + $items_per_page; - here you raise the end for your last loop by another 1000 and therefor get ?start=25001&end=27000&seq=25.
Try $padding = $total_xml_records; instead, this will get you ?start=25001&end=25197&seq=25.
Anyway your code is quite complicated. Try this:
$total_xml_records = 25197; // index 0 .. 25196
$offset = 0;
$counter = 0;
while ($offset < $total_xml_records) {
echo "\n";
echo $static_url . "/sc_vuln_query-compliance.php?start=".($offset)."&end=".(min($offset+$items_per_page-1, $total_xml_records-1))."&seq=".($counter++);
$offset += $items_per_page;
}

Related

PHP API offset Pagination

I have the following code but I am not sure how to loop and offset records to get the next 20 records using the same function loop.
gameid is zero on the first call and on the second call the gameid is 21.
$result = new ArrayObject();
$count = 0;
foreach($response as &$game) {
$game = get_object_vars($game);
if ($game['gameType'] == $gametype )
{
$result->append(array($game['gameName'], $game['gameType']));
if ($count == $gameid+19) break;
$count ++ ;
}
}
Thank You
I think you should use the concept of page size and page index.
In you case seem like you want page size of 20. Sending second request with gameid mean you want page size 20 and page index 1 (instead of 0).
So consider code like this:
$count = 0;
$pageSize = 20; // this can be const or come as param
$pageIndex = 0; // this should be as params
foreach($response as &$game) {
$game = get_object_vars($game);
if ($game['gameType'] == $gametype ) {
$count++ ;
if ($count > ($pageSize * $pageIndex))
$result->append(array($game['gameName'], $game['gameType']));
// if you over the request chunk break
if ($count > ($pageSize * ($pageIndex + 1)) break;
}
}

Get lowest price on sum of combinations in given array

This code is working fine when the array length is 8 or 10 only. When we are checking this same code for more than 10 array length.it get loading not showing the results.
How do reduce my code. If you have algorithm please share. Please help me.
This program working flow:
$allowed_per_room_accommodation =[2,3,6,5,3,5,2,5,4];
$allowed_per_room_price =[10,30,60,40,30,50,20,60,80];
$search_accommodation = 10;
i am get subsets = [5,5],[5,3,2],[6,4],[6,2,2],[5,2,3],[3,2,5]
Show lowest price room and then equal of 10 accommodation; output like as [5,3,2];
<?php
$dp=array(array());
$GLOBALS['final']=[];
$GLOBALS['room_key']=[];
function display($v,$room_key)
{
$GLOBALS['final'][] = $v;
$GLOBALS['room_key'][] = $room_key;
}
function printSubsetsRec($arr, $i, $sum, $p,$dp,$room_key='')
{
// If we reached end and sum is non-zero. We print
// p[] only if arr[0] is equal to sun OR dp[0][sum]
// is true.
if ($i == 0 && $sum != 0 && $dp[0][$sum]) {
array_push($p,$arr[$i]);
array_push($room_key,$i);
display($p,$room_key);
return $p;
}
// If $sum becomes 0
if ($i == 0 && $sum == 0) {
display($p,$room_key);
return $p;
}
// If given sum can be achieved after ignoring
// current element.
if (isset($dp[$i-1][$sum])) {
// Create a new vector to store path
// if(!is_array(#$b))
// $b = array();
$b = $p;
printSubsetsRec($arr, $i-1, $sum, $b,$dp,$room_key);
}
// If given $sum can be achieved after considering
// current element.
if ($sum >= $arr[$i] && isset($dp[$i-1][$sum-$arr[$i]]))
{
if(!is_array($p))
$p = array();
if(!is_array($room_key))
$room_key = array();
array_push($p,$arr[$i]);
array_push($room_key,$i);
printSubsetsRec($arr, $i-1, $sum-$arr[$i], $p,$dp,$room_key);
}
}
// Prints all subsets of arr[0..n-1] with sum 0.
function printAllSubsets($arr, $n, $sum,$get=[])
{
if ($n == 0 || $sum < 0)
return;
// Sum 0 can always be achieved with 0 elements
// $dp = new bool*[$n];
$dp = array();
for ($i=0; $i<$n; ++$i)
{
// $dp[$i][$sum + 1]=true;
$dp[$i][0] = true;
}
// Sum arr[0] can be achieved with single element
if ($arr[0] <= $sum)
$dp[0][$arr[0]] = true;
// Fill rest of the entries in dp[][]
for ($i = 1; $i < $n; ++$i) {
for ($j = 0; $j < $sum + 1; ++$j) {
// echo $i.'d'.$j.'.ds';
$dp[$i][$j] = ($arr[$i] <= $j) ? (isset($dp[$i-1][$j])?$dp[$i-1][$j]:false) | (isset($dp[$i-1][$j-$arr[$i]])?($dp[$i-1][$j-$arr[$i]]):false) : (isset($dp[$i - 1][$j])?($dp[$i - 1][$j]):false);
}
}
if (isset($dp[$n-1][$sum]) == false) {
return "There are no subsets with";
}
$p;
printSubsetsRec($arr, $n-1, $sum, $p='',$dp);
}
$blockSize = array('2','3','6','5','3','5','2','5','4');
$blockvalue = array('10','30','60','40','30','50','20','60','80');
$blockname = array("map","compass","water","sandwich","glucose","tin","banana","apple","cheese");
$processSize = 10;
$m = count($blockSize);
$n = count($processSize);
// sum of sets in array
printAllSubsets($blockSize, $m, $processSize);
$final_subset_room = '';
$final_set_room_keys = '';
$final_set_room =[];
if($GLOBALS['room_key']){
foreach ($GLOBALS['room_key'] as $set_rooms_key => $set_rooms) {
$tot = 0;
foreach ($set_rooms as $set_rooms) {
$tot += $blockvalue[$set_rooms];
}
$final_set_room[$set_rooms_key] = $tot;
}
asort($final_set_room);
$final_set_room_first_key = key($final_set_room);
$final_all_room['set_room_keys'] = $GLOBALS['room_key'][$final_set_room_first_key];
$final_all_room_price['set_room_price'] = $final_set_room[$final_set_room_first_key];
}
if(isset($final_all_room_price)){
asort($final_all_room_price);
$final_all_room_first_key = key($final_all_room_price);
foreach ($final_all_room['set_room_keys'] as $key_room) {
echo $blockname[$key_room].'---'. $blockvalue[$key_room];
echo '<br>';
}
}
else
echo 'No Results';
?>
I'm assuming your task is, given a list rooms, each with the amount of people it can accommodate and the price, to accommodate 10 people (or any other quantity).
This problem is similar to 0-1 knapsack problem which is solvable in polynomial time. In knapsack problem one aims to maximize the price, here we aim to minimize it. Another thing that is different from classic knapsack problem is that full room cost is charged even if the room is not completely occupied. It may reduce the effectiveness of the algorithm proposed at Wikipedia. Anyway, the implementation isn't going to be straightforward if you have never worked with dynamic programming before.
If you want to know more, CLRS book on algorithms discusses dynamic programming in Chapter 15, and knapsack problem in Chapter 16. In the latter chapter they also prove that 0-1 knapsack problem doesn't have trivial greedy solution.

PHP How do I loop through pages of this api?

So basically I am trying to get the sum of AveragePrice of every single page on this api. Right now it only gets first page the things i've tried have only gotten it to go on an endless loop crashing wamp. Heres my code for 1 page of working.
I am just really unsure how I can get it to loop through pages and get sum of every page.
<?php
function getRap($userId){
$url = sprintf("https://www.roblox.com/Trade/InventoryHandler.ashx?userId=" . $userId . "&filter=0&page=1&itemsPerPage=14");
$results = file_get_contents($url);
$json = json_decode($results, true);
$data = $json['data']['InventoryItems'];
$rap = 0;
foreach($data as $var) {
$rap += $var['AveragePrice'];
}
echo $rap;
}
$userId = 1;
getRap($userId);
?>
You may get better answers by looking into the API you are working with regarding how many pages to look for. You want to loop until you hit the max pages. There should be an value in the result of your request that tells you that you've asked for a page that doesn't exist (ie. no more results). If you can get a total number of results to search for then you could do a for loop with that as your limit.
//Change the function to accept the page number as a variable
function getRap($userId, $i){
$url = sprintf("https://www.roblox.com/Trade/InventoryHandler.ashx?userId=" . $userId . "&filter=0&page=" . $i . "&itemsPerPage=14");
//work out how many pages it takes to include your total items
// ceil rounds a value up to next integer.
// ceil(20 / 14) = ceil(1.42..) == 2 ; It will return 2 and you will look for two pages
$limit = ceil($totalItems / $itemsPerPage);
// Then loop through calling the function passing the page number up to your limit.
for ($i = 0; $i < $limit; $i++) {
getRap($userId, $i);
}
If you cannot get the total number of items, you could loop while a fail state hasn't occured
// look for a fail state inside your getRap()
function getRap($userId, $i) {
if ($result = error) { //you will have to figure out what it returns on a fail
$tooMany = TRUE;
}
}
for ($i = 0; $tooMany !== TRUE ; $i++) {
getRap($userId, $i);
}
Edit: Reviewing my answer, looking for the fail state inside your function is poor form (and won't work because of the scope of the variable in this case). You could pass the variable back and forth, but I'll leave that part up to you.
To get the total, make sure that your function doesn't print the result (echo $rap) but returns it for further use.
Full example
<?php
function getRap($userId, $i){
$url = sprintf("https://www.roblox.com/Trade/InventoryHandler.ashx?userId=" . $userId . "&filter=0&page=" . $i . "&itemsPerPage=25");
$results = file_get_contents($url);
$json = json_decode($results, true);
if ($json['msg'] == "Inventory retreived!") {
$data = $json['data']['InventoryItems'];
$rap = 0;
foreach($data as $var) {
$rap += $var['AveragePrice'];
}
return $rap;
} else {
return FALSE;
}
}
$total = 0;
$userId = 1;
for ($i = 0; $i < 1000 /*arbitrary limit to prevent permanent loop*/ ; $i++) {
$result = getRap($userId, $i);
if ($result == FALSE) {
$pages = $i;
break;
} else {
$total += getRap($userId, $i);
}
}
echo "Total value of $total, across $pages pages";
?>

PHP script not executing properly shows blank page after processing

i've been dealing with this annoying problem lately which consists of a php script that is supposed to execute quite heavy processing.
This script has a loop that makes comparisons around 25000*25000
i have set maximum time out as 10800
but when i use $time = time(); in the begining of the script
and echo $time - time() at each iteration
script stops after 497 secs
Please help me figure out what could possibly be wrong with the script that i see a blank page after 497 seconds.
Thanks.
EDIT:
while($a<count($data))
{
$AL = (error_get_last());
if($AL['type']==8)
var_dump($AL);
$i=0;
$compdata[$a] = array();
$row = explode("~",$data[$a]);
$dl[$a] = 0;
while($i<count($data))
{
$i += 1;
if(($i-1)==$a)
continue;
$rowc = explode("~",$data[$i-1]);
$j=0;
$cn = 0;
$tw = 0;
$kcv = "";
while($j<$kc)
{
if(Matcher($row[$kcn[$j][0]],$rowc[$kcn[$j][1]],$MCOUNT,$R))
{
$cn += 1;
$tw += $weight[$j];
$kcv .= $kcn[$j][2];
}
$j += 1;
}
if($tw != 0)
{
$compdata[$a][$i-1] = strval($i).$kcv;
$dl[$a] += $tw;
}
}
$compdata[$a] = join(",",$compdata[$a]);
$a += 1;
}
total loop run is about 25000*25000*10
Have you checked in your php.ini execution time

php - while loop is itering double the times expected and nested for loop is iterating 1.5 times more than expected

This script is supposed to to get a multidimensional array and iterate through the values.
The array size is 10 and each element should contain an associative array:
$games[0] => array('foo' => 'bar')
$games[1] => array('foo1' => 'bar1')
etc..
The while loop should iterate 5 times in this example. The for loop should iterate 10 times for each iteration of the while loop.
So I am expecting the echo to be:
countwhile = 5 countfor = 50 totalgames = 50
but im actually getting
countwhile = 5 countfor = 150 totalgames = 150
I believe $games array is not the problem because i have have made that call below before and have used print_r to view the contents and it is as expected.
This whole code is not in a function or class just as is on my index.php page, could the problem be to do with the variable scopes?
$totalruns = 5;
$endindx = 10;
$startindx = 0;
$countwhile = 0;
$countfor = 0;
$totalfilesize = 0;
$totalgames = 0;
$sizeof = 0;
while($totalruns > 0)
{
$games = $feedHandler->getGames($startindx, $endindx);
$sizeof = sizeof($games);
for($i=0; $i<$sizeof; $i++)
{
$totalfilesize += $games[$i]['swf_file_size'];
$countfor++;
}
$startindx += 10;
$endindx += 10;
$totalruns -= 1;
$totalgames += $sizeof;
unset($games);
}
echo'<p>' . ' countwhile = ' . $countwhile . ' countfor = ' . $countfor . '</p>';
problem 1:
$sizeof = sizeof($games)-1;
explain 1:
for($i=0, $sizeof = sizeof($games);$i<=$sizeof;$i++)
the above will execute 11 times is the sizeof($games) is 10
So, either
for($i=1, $sizeof = sizeof($games);$i<=$sizeof;$i++)
or
for($i=0, $sizeof=sizeof($games)-1;$i<=$sizeof;$i++)
problem 2 :
$e = sizeof($games);
explain 2 :
$e = count($games);
...
$e += $e;
If the final size of $games is 50, you just sum it to 100
so, it some kind of logic problem
I know the answer has been accepted, but thought I'd refactor and make this a little more clean.
function retrieveGamesInfo($limit, $start = 0)
{
$feedHandler = new FeedHandler(); // ignore this, just for testing to simluate your call
if ($start > $limit)
throw new Exception("Start index must be within the limit");
$result = Array(
'TotalGames' => 0,
'TotalFileSize' => 0
);
// iterate over the results in groups of 10
$range = $start;
while ($range < $limit)
{
$range_end = $range + 10; // change me to play with the grab amount
if ($range_end > $limit)
$range_end = $limit;
// grab the next 10 entries
$games = $feedHandler->getGames($range,$range_end);
$result['TotalGames'] += count($games);
foreach ($games as $game)
$result['TotalFileSize'] += $game['swf_file_size'];
$range = $range_end;
}
return $result;
}
var_dump(retrieveGamesInfo(50));
based one everything I've read and taken in, this should be a good supplement. The above provides the following result:
array(2) {
["TotalGames"]=>
int(50)
["TotalFileSize"]=>
int(275520)
}
As i said in my comment $e is overwritten at each loop, so what you have in $e at the end is just the last count of elements in $games *2.
Added with ajreal issues this means results are what your code is expected to render :-) and I'm quite sure your last $game is not just 10 elements but 50. Quiet sure... but it's hard to read.

Categories