The problem -> I need to find out the percentage of overlap between two routes.
Solution tried so far -> I tried passing the origin and destination (along with the key of course) to the following URL
https://maps.googleapis.com/maps/api/directions/json
and parsed the json response accordingly. Here is my code snippet -
$endpoint = 'https://maps.googleapis.com/maps/api/directions/json?origin='.$startLatitude1.','.$startLongitude1.'&destination='.$endLatitude1.','.$endLongitude1.'&key='.$mykey;
$json1 = file_get_contents($endpoint.http_build_query(array())); //array is empty here
$data1 = json_decode($json1);
if ($data1->status === 'OK') {
$endpoint = 'https://maps.googleapis.com/maps/api/directions/json?origin='.$startLatitude2.','.$startLongitude2.'&destination='.$endLatitude2.','.$endLongitude2.'&key='.$mykey;
$json2 = file_get_contents($endpoint.http_build_query(array())); //array is empty here
$data2 = json_decode($json2);
$polyline = array();
if ($data2->status === 'OK') {
$route2 = $data2->routes[0];
foreach ($route2->legs as $leg2) {
foreach ($leg2->steps as $step2) {
$polyline[$step2->polyline->points] = $step2->distance->value;
}
}
}
$overlap = 0;
$totalDistance = 0;
$route1 = $data1->routes[0];
foreach ($route1->legs as $leg1) {
$totalDistance = $leg1->distance->value;
foreach ($leg1->steps as $step1) {
if (array_key_exists($step1->polyline->points, $polyline)) {
$overlap = $overlap + $step1->distance->value;
}
}
}
echo 'Total Distance -> '.$totalDistance;
echo 'Overlap -> '.$overlap.'<br>';
}
So we are first traversing route 1 and storing the polylines as key in an associative array with distance as the value. Next we traverse route 2 and check if polylines from route 2 is already present in the associative array created earlier.
The problem -> This works until and unless the roads are straight. Let's assume there are 4 points - A, B, C, D and all are in a straight line in that order. Person X wants to go from A to D whereas person Y wants to go from B to C. So there is an overlap of B-C. But because the polylines will never match (origin and destination being different for X & Y), my code will not detect any overlap.
Any other way out?
Related
I have a problem with my results array, what I initially intended to have is something like this
$promises = [
'0' => $client->getAsync("www.api.com/opportunities?api=key&page=1fields=['fields']"),
'1' => $client->getAsync("www.api.com/opportunities?api=key&page=2fields=['fields']"),
'2' => $client->getAsync("www.api.com/opportunities?api=key&page=3fields=['fields']")
];
An array of request promises, I will use it because I want to retrieve a collection of data from the API that I am using. This is what the API first page looks like
In my request I want to get page 2,3,4.
This is how page 2 looks like
I made a do while loop on my PHP script but it seems to run an infinite loop
This is how it should work. First I run the initial request then get totalRecordCount = 154 and subtract it to recordCount = 100 if difference is != 0 it run it again and change the $pageNumber and push it to the promises.
This is my function code.Here's my code
function runRequest(){
$promises = [];
$client = new \GuzzleHttp\Client();
$pageCounter = 1;
$globalCount = 0;
do {
//request first and then check if has difference
$url = 'https://api.com/opportunities_dates?key='.$GLOBALS['API_KEY'].'&page='.$pageCounter.'&fields=["fields"]';
$initialRequest = $client->getAsync($url);
$initialRequest->then(function ($response) {
return $response;
});
$initialResponse = $initialRequest->wait();
$initialBody = json_decode($initialResponse->getBody());
$totalRecordCount = $initialBody->totalRecordCount;//154
$recordCount = $initialBody->recordCount;//100
$difference = $totalRecordCount - $recordCount;//54
$pageCounter++;
$globalCount += $recordCount;
array_push($promises,$url);
} while ($totalRecordCount >= $globalCount);
return $promises;
}
$a = $runRequest();
print_r($a); //contains array of endpoint like in the sample above
There is an endless loop because you keep looping when the total record count equals the global count. Page 3 and above have 0 records, so the total will be 154. Replacing the >= with a > will solve the loop.
However, the code will still not work as you expect it to do. For each page, you prepare a request with getAsync() and immediately do a wait(). The then statement does nothing. It returns the response, which it already does by default. So in practice, these are all sync requests.
Given that the page size is constant, you can calculate the pages you need based on the information given on the first request.
function runRequest(){
$promises = [];
$client = new \GuzzleHttp\Client();
$url = 'https://api.com/opportunities_dates?key='.$GLOBALS['API_KEY'].'&fields=["fields"]';
// Initial request to get total record count and page count
$initialRequest = $client->getAsync($url.'&page=1');
$initialResponse = $initialRequest->wait();
$initialBody = json_decode($initialResponse->getBody());
$promises[] = $initialRequest;
$totalRecordCount = $initialBody->totalRecordCount;//154
$pageSize = $initialBody->pageSize;//100
$nrOfPages = ceil($totalRecordCount / $pageSize);//2
for ($page = 2; $page <= $nrOfPages; $page++) {
$promises[] = $client->getAsync($url.'&page='.$page);
}
return $promises;
}
$promises = runRequest();
$responses = \GuzzleHttp\Promise\unwrap($promises);
Note that the function now returns promises and not URLs as strings.
It doesn't matter that the first promise is already settled. The unwrap function will not cause another GET request for page 1, but return the existing response. For all other pages, the requests are done concurrently.
I need to traverse the following type of structures:
P
/ | \
E1 E2 E3 .....
/ \ / \ |
V1 V2 V1 V2 V3 .....
| | | | / \
T1 T2 T3 T4 T5 T6 .....
In order to form an associative array with the following elements:
V1(key) = [T1(E1), T3(E2), ...]
V2(key) = [T2(E1), T4(E2), ...]
V3(key) = [T5(E3), T6(E3), ...]
.....
Now here comes the tricky part: the structure is actually simplified. I don't know beforehand how many E-level nodes I'll actually need to deal with (3 in the drawing), or how many V-level nodes each of them has (but at least 1 will be there), and furthermore, each V-level node may also have multiple T-nodes.
I tried using a recursion function to do this (in PHP). I'll simplify the code because it has weird methods regarding some objects that don't really matter to the discussion. My current attempt results in:
V1(key) = [T1(E1)]
V2(key) = [T2(E1)]
That I think means that the traversal is only occurring going down the first E-level "branch".
This is my code:
$result = [];
$traverser = function($node) use (&$traverser, &$result) {
$children = $node->getChildrenArray();
foreach($children as $key=>$child){
if ($child->nodeType() == 'v_node') {
$v_node_key = $child->name;
$t_nodes = $child->getChildrenArray();
if ( !array_key_exists($v_node_key, $results) ){
$results[$v_node_key] = [];
}
foreach($t_nodes as $keyt=>$t_node) {
$info_array = $t_node->toArray();
array_push($results[$v_node_key], $info_array);
}
} else if ($child->nodeType() == 'e_node') {
// keep digging
return $traverser($child);
}
}
};
$traverser($p_node);
I think the problem is that once I call the $traverser function within the foreach it won't come back and resume from the previous state.
Can anyone advise on how I should be tackling this to get the result I placed above?
Well, this is a bit awkward and I'm still not entirely sure if this is the right motive, but I solved this by removing the return in my code.
I thought that the return would allow me to exit the nested function call, but rather I think it jumped out of the first function call (the $traverser($p_node); line).
Even so, by changing the return $traverser($child); line to $traverser($child); it did what it had to do.
Hope this helps anyone!
I not show about what error you got but i suggest you to change you function to be this
function traverser($results, $node) {
$children = $node->getChildrenArray();
foreach($children as $key=>$child){
if ($child->nodeType() == 'v_node') {
$v_node_key = $child->name;
$t_nodes = $child->getChildrenArray();
if ( !array_key_exists($v_node_key, $results) ){
$results[$v_node_key] = [];
}
foreach($t_nodes as $keyt=>$t_node) {
$info_array = $t_node->toArray();
array_push($results[$v_node_key], $info_array);
}
} else if ($child->nodeType() == 'e_node') {
// keep digging
return traverser($child);
}
}
return $results;
}
Hope this help
Well, since you know that you'll have P->E->V->T-nodes, you could simply go for multiple foreach-loops, like this
foreach($p_node->getChildren() as $e_node) {
$e_node_key = $e_node->name;
foreach($e_node->getChildren() as $v_node) {
$v_node_key = $v_node->name;
foreach($v_node->getChildren() as $t_node) {
$t_node_key = $t_node->name;
// do whatever it needs to array_push to results
}
}
}
In a previous Using R, how to reference variable variables (or variables variable) a la PHP[post]
I asked a question about something in R analagous to PHP $$ function:
Using R stats, I want to access a variable variable scenario similar to PHP double-dollar-sign technique: http://php.net/manual/en/language.variables.variable.php
Specifically, I am looking for a function in R that is equivalent to $$ in PHP.
The get( response works for strings (characters).
lapply is a way to loop over lists
Or I can loop over and get the values ...
for(name in names(vars))
{
val = vars[[name]];
I still haven't had the $$ function in R answered, although the lapply solved what I needed in the moment.
`$$` <- function
that allows any variable type to be evaluated. That is still the question.
UPDATES
> mlist = list('four'="score", 'seven'="years");
> str = 'mlist$four'
> mlist
$four
[1] "score"
$seven
[1] "years"
> str
[1] "mlist$four"
> get(str)
Error in get(str) : object 'mlist$four' not found
> mlist$four
[1] "score"
Or how about attributes for an object such as mobj#index
UPDATES #2
So let's put specific context on the need. I was hacking the texreg package to build a custom latex output of 24 models of regression for a research paper. I am using plm fixed effects, and the default output of texreg uses dcolumns to center, which I don't like (I prefer r#{}l, so I wanted to write my own template. The purpose for me, to code this, is for me to write extensible code that I can use again and again. I can rebuild my 24 tables across 4 pages in seconds, so if the data change, or if I want to tweak the function, I immediately have a nice answer. The power of abstraction.
As I hacked this, I wanted to get more than the number of observations, but also the number of groups, which can be any user defined index. In my case it is "country" (wait for it, hence, the need for variable variables).
If I do a lookup of the structure, what I want is right there: model$model#index$country which would be nice to simply call as $$('model$model#index$country'); where I can easily build the string using paste. Nope, this is my workaround.
getIndexCount = function(model,key="country")
{
myA = attr(summary(model)$model,"index");
for(i in 1:length(colnames(myA)))
{
if(colnames(myA)[i] == key) {idx = i; break;}
}
if(!is.na(idx))
{
length(unique(myA[,idx]));
} else {
FALSE;
}
}
UPDATES #3
Using R, on the command line, I can type in a string and it gets evaluated. Why can't that internal function be directly accessed, and the element captured that then gets printed to the screen?
There is no equivalent function in R. get() works for all types, not just strings.
Here is what I came up with, after chatting with the R-bug group, and getting some ideas from them. KUDOS!
`$$` <- function(str)
{
E = unlist( strsplit(as.character(str),"[#]") );
k = length(E);
if(k==1)
{
eval(parse(text=str));
} else {
# k = 2
nstr = paste("attributes(",E[1],")",sep="");
nstr = paste(nstr,'$',E[2],sep="");
if(k>2) {
for(i in 3:k)
{
nstr = paste("attributes(",nstr,")",sep="");
nstr = paste(nstr,'$',E[i],sep="");
}
}
`$$`(nstr);
}
}
Below are some example use cases, where I can directly access what the str(obj) is providing... Extending the utility of the '$' operator by also allowing '#' for attributes.
model = list("four" = "score", "seven"="years");
str = 'model$four';
result = `$$`(str);
print(result);
matrix = matrix(rnorm(1000), ncol=25);
str='matrix[1:5,8:10]';
result = `$$`(str);
print(result);
## Annette Dobson (1990) "An Introduction to Generalized Linear Models".
## Page 9: Plant Weight Data.
ctl <- c(4.17,5.58,5.18,6.11,4.50,4.61,5.17,4.53,5.33,5.14);
trt <- c(4.81,4.17,4.41,3.59,5.87,3.83,6.03,4.89,4.32,4.69);
group <- gl(2, 10, 20, labels = c("Ctl","Trt"));
weight <- c(ctl, trt);
lm.D9 <- lm(weight ~ group);
lm.D90 <- lm(weight ~ group - 1); # omitting intercept
myA = anova(lm.D9); myA; str(myA);
str = 'myA#heading';
result = `$$`(str);
print(result);
myS = summary(lm.D90); myS; str(myS);
str = 'myS$terms#factors';
result = `$$`(str);
print(result);
str = 'myS$terms#factors#dimnames';
result = `$$`(str);
print(result);
str = 'myS$terms#dataClasses#names';
result = `$$`(str);
print(result);
After realizing the back-tick can be a bit tedious, I chose to update the function, calling it access
access <- function(str)
{
E = unlist( strsplit(as.character(str),"[#]") );
k = length(E);
if(k==1)
{
eval(parse(text=str));
} else {
# k = 2
nstr = paste("attributes(",E[1],")",sep="");
nstr = paste(nstr,'$',E[2],sep="");
if(k>2) {
for(i in 3:k)
{
nstr = paste("attributes(",nstr,")",sep="");
nstr = paste(nstr,'$',E[i],sep="");
}
}
access(nstr);
}
}
I am a fairly comfortable PHP programmer, and have very little Python experience. I am trying to help a buddy with his project, the code is easy enough to write in Php, I have most of it ported over, but need a bit of help completing the translation if possible.
The target is to:
Generate a list of basic objects with uid's
Randomly select a few Items to create a second list keyed to the uid containing new
properties.
Test for intersections between the two lists to alter response accordingly.
The following is a working example of what I am trying to code in Python
<?php
srand(3234);
class Object{ // Basic item description
public $x =null;
public $y =null;
public $name =null;
public $uid =null;
}
class Trace{ // Used to update status or move position
# public $x =null;
# public $y =null;
# public $floor =null;
public $display =null; // Currently all we care about is controlling display
}
##########################################################
$objects = array();
$dirtyItems = array();
#CREATION OF ITEMS########################################
for($i = 0; $i < 10; $i++){
$objects[] = new Object();
$objects[$i]->uid = rand();
$objects[$i]->x = rand(1,30);
$objects[$i]->y = rand(1,30);
$objects[$i]->name = "Item$i";
}
##########################################################
#RANDOM ITEM REMOVAL######################################
foreach( $objects as $item )
if( rand(1,10) <= 2 ){ // Simulate full code with 20% chance to remove an item.
$derp = new Trace();
$derp->display = false;
$dirtyItems[$item->uid] = $derp; //# <- THIS IS WHERE I NEED THE PYTHON HELP
}
##########################################################
display();
function display(){
global $objects, $dirtyItems;
foreach( $objects as $key => $value ){ // Iterate object list
if( #is_null($dirtyItems[$value->uid]) ) // Print description
echo "<br />$value->name is at ($value->x, $value->y) ";
else // or Skip if on second list.
echo "<br />Player took item $value->uid";
}
}
?>
So, really I have most of it sorted I am just having trouble with Python's version of an Associative array, to have a list whose keys match the Unique number of Items in the main list.
The output from the above code should look similar to:
Player took item 27955
Player took item 20718
Player took item 10277
Item3 is at (8, 4)
Item4 is at (11, 13)
Item5 is at (3, 15)
Item6 is at (20, 5)
Item7 is at (24, 25)
Item8 is at (12, 13)
Player took item 30326
My Python skills are still course, but this is roughly the same code block as above.
I've been looking at and trying to use list functions .insert( ) or .setitem( ) but it is not quite working as expected.
This is my current Python code, not yet fully functional
import random
import math
# Begin New Globals
dirtyItems = {} # This is where we store the object info
class SimpleClass: # This is what we store the object info as
pass
# End New Globals
# Existing deffinitions
objects = []
class Object:
def __init__(self,x,y,name,uid):
self.x = x # X and Y positioning
self.y = y #
self.name = name #What will display on a 'look' command.
self.uid = uid
def do_items():
global dirtyItems, objects
for count in xrange(10):
X=random.randrange(1,20)
Y=random.randrange(1,20)
UID = int(math.floor(random.random()*10000))
item = Object(X,Y,'Item'+str(count),UID)
try: #This is the new part, we defined the item, now we see if the player has moved it
if dirtyItems[UID]:
print 'Player took ', UID
except KeyError:
objects.append(item) # Back to existing code after this
pass # Any error generated attempting to access means that the item is untouched by the player.
# place_items( )
random.seed(1234)
do_items()
for key in objects:
print "%s at %s %s." % (key.name, key.x, key.y)
if random.randint(1, 10) <= 1:
print key.name, 'should be missing below'
x = SimpleClass()
x.display = False
dirtyItems[key.uid]=x
print ' '
objects = []
random.seed(1234)
do_items()
for key in objects:
print "%s at %s %s." % (key.name, key.x, key.y)
print 'Done.'
So, sorry for the long post, but I wanted to be through and provide both sets of full code. The PhP works perfectly, and the Python is close. If anyone can point me in the correct direction it would be a huge help.
dirtyItems.insert(key.uid,x) is what i tried to use to make a list work as an Assoc array
Edit: minor correction.
You're declaring dirtyItems as an array instead of a dictionary. In python they're distinct types.
Do dirtyItems = {} instead.
Make a dictionary instead of an array:
import random
import math
dirtyItems = {}
Then you can use like:
dirtyItems[key.uid] = x
I am creating a custom social network for one of my clients.
In this I am storing the friends of a user in the form of CSV as shown below in the user table
uid user_name friends
1 John 2
2 Jack 3,1
3 Gary 2,4
4 Joey 3
In the above scenario if the logged in user is John and if he visits the profile page of Joey, the connection between them should appear as
John->Jack->Gary->Joey
I am able to establish the connection at level 1 i.e
If Jack visits Joey's profile I am able to establish the following :
Jack->Gary->Joey
But for the 2nd level I need to get into the same routine of for loops which I know is not the right solution + I am not able to implement that as well.
So, can someone please help me with this?
Thanks in Advance,
Akash
P:S I am not in a position to change the db architecture :(
Here's some bfs code I had written in ruby; it should give you a good enough idea of how things work to translate it to php. the other change you'll need to make is to replace graph[current] with a db query to get the current user's friends.
def bfs(graph, start, stop)
queue = [start]
visited = {}
parents = {}
current = nil
while true
if queue.empty?
return nil
end
current = queue.shift
if current == stop
return read_path(current, parents)
end
visited[current] = true
graph[current].each do |i|
if not visited[i] and not queue.index(i)
parents[i] = current
queue.push(i)
end
end
end
end
def read_path(node, parents)
a = [node]
while parents[node]
a.push(parents[node])
node = parents[node]
end
return a.reverse
end
GRAPH = {
"a" => ["b", "c"],
"b" => ["c", "d"],
"c" => ["a", "e"],
"d" => ["b", "c", "f"],
"e" => ["c", "f"]
}
path = bfs(GRAPH, "a", "f")
p path
Here's some sample code:
<?php
$currentUID = 1; // The logged in user
$pageUID = 4; // The user whose page is being visited
// Parse the CSV
$csv = explode("\n", $csvData);
$csvlen = count($csv);
for($i=0;$i<$csvlen;$i++) {
$csv[$i] = explode(",", $csv[$i]);
}
function getFriends($csv, $uid) {
foreach($csv as $user)
if($user[0] == $uid)
return explode(',', $user[2]);
}
$userFriends = getFriends($csv, $currentUID);
$pageFriends = getFriends($csv, $pageUID);
$friendPool = array();
foreach($userFriends as $friend) {
$hisFriends = getFriends($friend);
foreach($hisFriends as $subFriend) {
if(in_array($subFriend, $pageFriends)) {
if(isset($friendPool[$friend]))
$friendPool[$friend][] = $subFriend;
else
$friendPool[$friend] = array( $subFriend );
}
}
}
foreach($friendPool as $friend=>$subFriends)
foreach($subFriends as $subFriend)
echo "$currentUID -> $friend -> $subFriend -> $pageUID\n";