I am using TomTom API to retrieve Traffic Data in PBF format
example /traffic/map/{versionNumber}/tile/flow/{style}/{zoom}/{x}/{y}.{format}
api call tried https://api.tomtom.com/traffic/map/4/tile/flow/relative0/12/1207/1539.pbf?tileSize=256&key=*****
I have only just realised that the x,y coordinates are the x and y coordinates corresponding to the tile's position on the grid for that zoom level, and not geographical.
To overcome this, I found the following JavaScript code to convert from z/x/y to lat/long
function tileZXYToLatLon(zoomLevel, x, y) {
const MIN_ZOOM_LEVEL = 0
const MAX_ZOOM_LEVEL = 22
if (
zoomLevel == undefined ||
isNaN(zoomLevel) ||
zoomLevel < MIN_ZOOM_LEVEL ||
zoomLevel > MAX_ZOOM_LEVEL
) {
throw new Error(
"Zoom level value is out of range [" +
MIN_ZOOM_LEVEL.toString() +
"," +
MAX_ZOOM_LEVEL.toString() +
"]"
)
}
let z = Math.trunc(zoomLevel)
let minXY = 0
let maxXY = Math.pow(2, z) - 1
if (x == undefined || isNaN(x) || x < minXY || x > maxXY) {
throw new Error(
"Tile x value is out of range [" +
minXY.toString() +
"," +
maxXY.toString() +
"]"
)
}
if (y == undefined || isNaN(y) || y < minXY || y > maxXY) {
throw new Error(
"Tile y value is out of range [" +
minXY.toString() +
"," +
maxXY.toString() +
"]"
)
}
let lon = (x / Math.pow(2, z)) * 360.0 - 180.0
let n = Math.PI - (2.0 * Math.PI * y) / Math.pow(2, z)
let lat = (180.0 / Math.PI) * Math.atan(0.5 * (Math.exp(n) - Math.exp(-n)))
return lat.toString() + "/" + lon.toString()
}
However, I am not very competent in JavaScript and would much rather use Python. Can anyone advise me how I can replicate this script into Pythonic format?
Related
While doing challenges on coderbyte i found someone else's solution. his code however was not working for 1 of the test cases, but i don't understand why.
challenge info: input is an array of 2 strings the first string contains 2 numbers representing the weights on both sides of a scale. the second string contains the weights u can use to try and balance the scale. goal: balance the scale with the least amount of weights (max 2) and output what weights you used.
the code outputs 1,6 which does balance the scale but the scale could also have been balanced by just one weight, 5. why doesn't the first "return" break out of the function?
function ScaleBalancing(strArr) {
const w1 = JSON.parse(strArr[0])[0];
const w2 = JSON.parse(strArr[0])[1];
let weights = JSON.parse(strArr[1]);
for (let i = 0; i < weights.length; i++) {
if (w1 + weights[i] === w2 || w2 + weights[i] === w1) {
return '' + weights[i]; // should return 5 and break out of function right?
}
//if this for loop is omitted the function returns 5
for (let j = i + 1; j < weights.length; j++) {
if (w1 + weights[i] + weights[j] === w2 ||
w2 + weights[i] + weights[j] === w1 ||
w1 + weights[i] === w2 + weights[j] ||
w2 + weights[i] === w1 + weights[j]) {
return '' + weights[i] + ',' + weights[j]; //this returns 1,6
}
}
}
return 'not possible';
}
// keep this function call here
ScaleBalancing(["[6, 1]", "[1, 10, 6, 5]"]);
The reason the is that the outer loop starts from 0 index. On that point the code don't know that 5 will come sometime in array.
For the first number which is 1 the condition (w1 + weights[i] === w2 || w2 + weights[i] === w1) is false so it goes to nested for loop.
If you put 5 before 1 the code will return 5
function ScaleBalancing(strArr) {
const w1 = JSON.parse(strArr[0])[0];
const w2 = JSON.parse(strArr[0])[1];
let weights = JSON.parse(strArr[1]);
for (let i = 0; i < weights.length; i++) {
if (w1 + weights[i] === w2 || w2 + weights[i] === w1) {
return '' + weights[i]; // should return 5 and break out of function right?
}
//if this for loop is omitted the function returns 5
for (let j = i + 1; j < weights.length; j++) {
if (w1 + weights[i] + weights[j] === w2 ||
w2 + weights[i] + weights[j] === w1 ||
w1 + weights[i] === w2 + weights[j] ||
w2 + weights[i] === w1 + weights[j]) {
return '' + weights[i] + ',' + weights[j]; //this returns 1,6
}
}
}
return 'not possible';
}
// keep this function call here
console.log(ScaleBalancing(["[6, 1]", "[5, 10, 6, 1]"]));
I am trying to find the midpoint using duration traffic values(n1,n2,n3) in specified departure time(timeStamp) so that all the three-person have the same travel time (midpoint by Time). I'm using Google distance matrix.
I have been passing all three locations (a,b,c) & midpoint(d) based on the distance of the three locations.
I tried finding their midpoint by subtraction(all three), average(three of them) and subtracting with (Max and Min Values of n1,n2,n3) so that there traveling time becomes equal or less than the specified time(maxTime distance b/w three of them). Then point becomes the Midpoint
But I couldn't find a solution. Suggestions are much appreciated.
const maxTime = 5000;
var i = 0;
z = 0;
j = 0
//Distance Matrix Api
function getDistanceMatrix(a, b, c, d, timeStamp, googleWarnings, copyRights) {
clientMap.post(config_KEYS.DISTANCE_MATRIX_API + a + "|" + b + "|" + c + "&destinations=" + d.lat + "," + d.lng + "+&key=" + config_KEYS.GOOGLE_API_KEY + "&departure_time=" + timeStamp + "", function(gotDistanceResp, err) {
if (err) {
res.status(400).json(gotDistanceResp)
} else {
let n1 = gotDistanceResp.rows[0].elements[0].duration_in_traffic.value
let n2 = gotDistanceResp.rows[1].elements[0].duration_in_traffic.value
let n3 = gotDistanceResp.rows[2].elements[0].duration_in_traffic.value
// let minTime = Math.abs(n2 - n1)
let minTime = Math.round((n3 + n2 + n1) / 3)
if (n1 >= n2 && n1 >= n3) {
if (minTime <= maxTime) {
res.send(gotDistanceResp)
} else {
i++;
let arrayPoints = getDirectionApi(a, d, timeStamp, i)
}
} else {
if (n2 >= n1 && n2 >= n3) {
if (minTime <= maxTime) {
res.send(gotDistanceResp)
} else {
j++;
let arrayPoints = getDirectionApi(b, d, timeStamp, j)
}
} else {
if (n3 >= n1 && n3 >= n1) {
if (minTime <= maxTime) {
res.send(gotDistanceResp)
} else {
z++;
let arrayPoints = getDirectionApi(c, d, timeStamp, z)
}
} else {
res.send(gotDistanceResp)
}
}
}
}
})
}
//Get Direction Api
function getDirectionApi(a, b, timeStamp, r) {
clientMap.post(config_KEYS.DIRECTION_API + a + "&destination=" + b.lat + "," + b.lng + "&key=" + config_KEYS.GOOGLE_API_KEY + "&departure_time=" + timeStamp + "", function(route, error) {
if (route.geocoder_status == "ZERO_RESULTS" | route.status == "INVALID_REQUEST") {
res.status(400).send(route)
} else {
let googleWarnings = route.routes[0].warnings
let copyRights = route.routes[0].copyrights
let polyline = route.routes[0].overview_polyline.points
let decoded = decode(polyline)
let midPointCha = getDistanceMatrix(Location1, Location2, Location3, reversedMidArra[r])
}
})
}
Below, I have created an algorithm (in pseudocode) that minimizes the longest travel time:
Problem:
Given starting points A, B, and C:
Find a central location D
such that the travel duration from each point to D is similar. (where "similar" is defined as "within a specified tolerance"...for example, this could be set to 1 minute.)
Preparation:
Determine a candidate location for D:
the "center of gravity" or geographic midpoint.
(Average the x coordinates and the y coordinates.)
Set _Converged_ to false.
Execution:
While (not _Converged_) {
Query the travel time from each start location to point D.
If all three travel times are within the specified tolerance:
Then
_Converged_ = true // current point D is returned as acceptable
Else
Average the three travel times: avg
Identify the starting point with the longest travel time:
where Q is A, B, or C and t is the travel time.
Divide the average by t:
where p is avg/t
Compute a new point E between Q and D based on percentage p
(for example, if p is .66, then new point is 66% along
the vector from Q to D)
E = p(D - Q) + Q
Set D to this new point E
D = E
}
return D
The attached figure illustrates an example iteration.
Edit: I have implemented a proof of concept demonstration on CodePen.
Below is a sample of the code:
else { // Minimize the longest duration
// First, find the average duration
let avg = (n[0]+n[1]+n[2])/3;
// Divide the average by longest travel time
let p = avg / n[maxN];
// Compute a new point E between Q and D based on percentage p
// E = p(D - Q) + Q
// D = E
destination[0].lat = lerp(origins[maxN].lat,destination[0].lat,p);
destination[0].lng = lerp(origins[maxN].lng,destination[0].lng,p);
// Cycle again, waiting a bit to prevent server overload
setTimeout(calculateDistances, 500+Math.random()*100);
}
See DEMO
You can try below one, Which is more slimier like What James suggested but my point of view just find the path between A and D then find "p" point(Which is avg / n[maxN] *100) in the decoded path.
ex: if p is 73 then find the path between A and D decode for example it has 235 points then (Math.round((235/100)*73)=172) Pick 172 position latitude and longitude in the decoded path of A,D) and repeat process.
let arrOfMid = [];
//Distance Matrix Api
function getDistanceMatrix(a, b, c, d, timeStamp, i) {
clientMap.post(config_KEYS.DISTANCE_MATRIX_API + a + "|" + b + "|" + c + "&destinations=" + d.lat + "," + d.lng + "+&key=" + config_KEYS.GOOGLE_API_KEY + "&departure_time=" + timeStamp + "", function (gotDistanceResp, err) {
if (gotDistanceResp.status == "OVER_QUERY_LIMIT" | gotDistanceResp.status == "REQUEST_DENIED") {
res.status(400).json(gotDistanceResp)
}
else {
let n1 = gotDistanceResp.rows[0].elements[0].duration_in_traffic.value
let n2 = gotDistanceResp.rows[1].elements[0].duration_in_traffic.value
let n3 = gotDistanceResp.rows[2].elements[0].duration_in_traffic.value
let maxValue = Math.max(n1, n2, n3)
let minTime = Math.abs(n2 - n1)
let avg = Math.round((n3 + n2 + n1) / 3)
let value = (avg / maxValue) * 100
if (n1 >= n2 && n1 >= n3) {
if (arrOfMid.includes(gotDistanceResp.destination_addresses[0]) == true) {
res.send(gotDistanceResp)
}
else {
arrOfMid.push(d)
i++;
let arrayForTenPerc = getDirectionApi(a, d, timeStamp, value, i)
}
}
else {
if (n2 >= n1 && n2 >= n3) {
if (arrOfMid.includes(gotDistanceResp.destination_addresses[0]) == true) {
res.send(gotDistanceResp)
}
else {
arrOfMid.push(gotDistanceResp.destination_addresses[0])
j++;
let arrayPoints = getDirectionApi(b, d, timeStamp, value, j)
}
}
else {
if (n3 >= n1 && n3 >= n1) {
if (arrOfMid.includes(gotDistanceResp.destination_addresses[0]) === true) {
res.send(gotDistanceResp)
}
else {
arrOfMid.push(gotDistanceResp.destination_addresses[0])
z++;
let arrayPoints = getDirectionApi(c, d, timeStamp, value, z)
}
}
else {
res.send(gotDistanceResp)
}
}
}
}
})
}
//Get Direction Api
function getDirectionApi(a, b, timeStamp, r, i) {
clientMap.post(config_KEYS.DIRECTION_API + a + "&destination=" + b.lat + "," + b.lng + "&key=" + config_KEYS.GOOGLE_API_KEY + "&departure_time=" + timeStamp + "", function (route, error) {
if (route.geocoder_status == "ZERO_RESULTS" | route.status == "INVALID_REQUEST") {
res.status(400).send(route)
}
else {
let polyline = route.routes[0].overview_polyline.points
let decoded = decode(polyline)
let x = Math.round(decoded.length / 100 * r)
let midPointCha = getDistanceMatrix(Location1, Location2, Location3, decoded[x], timeStamp, i)
}
})
}
I have a java-script function that carries out a calculation. I would like to use the answer to that calculation in my php code.
document.write(Fixed((PoissonTerm( X, Y )),8,4))
Both values X and Y come from variables within my php code so
<?php
$valueofx;
$valueofy;
?>
In the ideal world I would like to to look like this
<?php
$thejavascriptvalue = document.write(Fixed((PoissonTerm( $valueofx, $valueofy )),8,4))
?>
I know this can't be done and i have 5 different values i need to pull and use. Is there anyway I can work around it? I dont mind refreshing the page or grabbing it from another page as long as i can have 5 values to use in my php code.
I would need to run the javascript 10 times before redirecting like
document.write(Fixed((PoissonTerm(0.1, 0 )),8,4))
document.write(Fixed((PoissonTerm( 8, 2 )),8,4))
document.write(Fixed((PoissonTerm( 6, 3 )),8,4))
below if the javascript
function Fixed( s, wid, dec ) {
// many combinations of possibilities
// maybe prepare for upcoming truncate
var z = 1
if (dec > 0) {
z /= Math.pow( 10, dec );
if (s < -z) s -= 0.5 * z;
else
if (s > z) s += 0.5 * z;
else
s = 0;
}
// assure a string
s = "" + s;
// chop neg, if any
var neg = 0;
if (s.charAt(0) == "-") {
neg = 2;
s = s.substring( 1, s.length );
}
// chop exponent, if any
var exp = "";
var e = s.lastIndexOf( "E" );
if (e < 0) e = s.lastIndexOf( "e" );
if (e > -1) {
exp = s.substring( e, s.length );
s = s.substring( 0, e );
}
// if dec > 0 assure "."; dp == index of "."
var dp = s.indexOf( ".", 0 );
if (dp == -1) {
dp = s.length;
if (dec > 0) {
s += ".";
dp = s.length - 1;
}
}
// assure leading digit
if (dp == 0) {
s = '0' + s;
dp = 1;
}
// not enough dec pl? add 0's
while ((dec > 0) && ((s.length - dp - 1) < dec))
s += "0";
// too many dec pl? take a substring
var places = s.length - dp - 1;
if (places > dec)
if (dec == 0)
s = s.substring( 0, dp );
else
s = s.substring( 0, dp + dec + 1 );
// recover exponent, if any
s += exp;
// recover neg, if any
if (neg > 0)
s = "-" + s;
// if not enough width, add spaces IN FRONT
// too many places? tough!
while (s.length < wid)
s = " " + s;
return s
}
function Prb( x ) {
if (x < 0) x = 0;
else
if (x > 1) x = 1;
return x;
}
function PosV( x ) {
if (x < 0) x = -x;
return x;
}
// FACTORIALS
function Fact( x ) {
// x factorial
var t=1;
while (x > 1)
t *= x--;
return t;
}
function LnFact( x ) {
// ln(x!) by Stirling's formula
// see Knuth I: 111
if (x <= 1) x = 1;
if (x < 12)
return Math.log( Fact(Math.round(x)) );
else {
var invx = 1 / x;
var invx2 = invx * invx;
var invx3 = invx2 * invx;
var invx5 = invx3 * invx2;
var invx7 = invx5 * invx2;
var sum = ((x + 0.5) * Math.log(x)) - x;
sum += Math.log(2*Math.PI) / 2;
sum += (invx / 12) - (invx3 / 360);
sum += (invx5 / 1260) - (invx7 / 1680);
return sum;
}
}
// POISSON
function PoissonPD( u, k ) {
// Peizer & Pratt 1968, JASA 63: 1416-1456
var s = k + (1/2);
var d1 = k + (2/3) - u;
var d2 = d1 + 0.02/(k+1);
var z = (1 + g(s/u)) / u;
z = d2 * Math.sqrt(z);
z = NormalP( z );
return z;
}
function PoissonTerm( u, k ) {
// by logs
return Math.exp( (k * Math.log(u)) - u - LnFact(k) );
}
function PoissonP( u, k ) {
// term-by-term summation
if (k >= 20) return PoissonPD( u, k );
else {
var sum = 0.0, j = 0;
while (j <= k)
sum += PoissonTerm( u, j++ );
if (sum > 1) sum = 1;
return sum;
}
}
function DoPoi( aform ) {
var u = PosV(parseFloat(aform.u.value));
aform.u.value = Fixed(u,10,4);
var k = PosV(parseInt(aform.k.value));
aform.k.value = Fixed(k,8,0);
aform.tnk.value = Fixed(PoissonTerm( u, k ),8,4);
var t = PoissonP( u, k );
aform.puk.value = Fixed(t,8,4);
aform.quk.value = Fixed(1-t,8,4);
}
This is very generic. You're going to have to modify this to your needs. But this will give you the basic idea:
<form name="thisform" action="phpPage.php" method="POST">
X: <input type="text" name="val_x" id="val_x" value="40" /><br />
Y: <input type="text" name="val_y" id="val_y" value="60" /><br />
<input type="button" onclick="sendForm();" value="send form"/>
</form>
JavaScript:
function sendForm(){
//Choose one of these methods:
//This will generate a string that you can use as a location.
//use $_GET in PHP to retrieve the values
var valofX = document.getElementById("val_x").value;
var valofy = document.getElementById("val_y").value;
generateURL = 'phpPage.php?val_x=' + valofX;
generateURL += '&val_y=' + valofy;
document.location = generateURL;
//This will submit the form.
//use $_POST in PHP to retrieve the values
document.getElementById("thisform").submit();
}
Once the form is submitted, or the location is sent, you'll need to grab the values in PHP:
$val_x = $_POST['val_x'];
$val_y = $_POST['val_y'];
//OR
$val_x = $_GET['val_x'];
$val_y = $_GET['val_y'];
You would use $_GET or $_POST depending on how the values are sent.
I'm using the following script to use dots as the thousands separator and commas as decimals separator that I got from this question.
var numero = 1000.00;
function formatThousands(n, dp) {
var s = ''+(Math.floor(n)),
d = n % 1,
i = s.length,
r = '';
while ((i -= 3) > 0) {
r = '.' + s.substr(i, 3) + r;
}
return s.substr(0, i + 3) + r + (d ? ',' + Math.round(d * Math.pow(10,dp||2)) : '');
}
alert(formatThousands(numero,2));
/// http://jsperf.com/compare-two-format-thousands
See also jsfiddle
This is working OK, except for integers.
For example, the number 1000 will return 1.000 and I want it to return 1.000,00 since the numbers refer to Euro currency.
How can I add the 2 decimals (cents) in every number?
Thanks for helping!
Does this work?
function formatThousands(n, dp) {
var s = ''+(Math.floor(n)), d = n % 1, i = s.length, r = '';
while ( (i -= 3) > 0 ) { r = '.' + s.substr(i, 3) + r; }
s = s.substr(0, i + 3) + r + (d ? ',' + Math.round(d * Math.pow(10,dp||2)) : '');
return s.charAt(-1) != ',' ? s+',00' : s;
}
EDIT:
How about this?
function formatThousands(n, dp) {
n = (''+n).split('.');
i = n[0];
d = !(n[1]) ? '00' : n[1];
n = i.match(/.{4}/g).join('.');
return n + ',' + d;
}
http://jsfiddle.net/XC3sS/12/
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I'm trying to understand what's going on in this code: http://js1k.com/2013-spring/demo/1396
This doesn't look like it's been minified or encoded in Base62 to me. When I paste it in Vim weird characters appear everywhere. Is there a way I can decode it?
This has been produced using the Data URI Scheme
https://en.wikipedia.org/wiki/Data_URI_scheme
The javascript file has been supplied as a URI which contains the file's contents. Lots of codes have been URL escaped, hence all the \s. And it may have been minified before that.
The data here is a whole HTML document. The first part is the start of the HTML file:
javascript:
'<!doctype html>\n<html>\n\t<head>\n\t\t<title>JS1k, 1k demo submission [1396]</title>\n\t\t<meta charset="utf-8" />\n\t</head>\n\t<body>\n\t\t<canvas id="c"></canvas>\n\t\t
After that an inline script:
var b = document.body;\n\t\t\tvar c = document.getElementsByTagName(\'canvas\')[0];\n\t\t\tvar a = c.getContext(\'2d\');\n\t\t\tdocument.body.clientWidth; // fix bug in webkit: http://qfox.nl/weblog/218\n\t\t
which you can easily decode as:
var b = document.body;
var c = document.getElementsByTagName('canvas')[0];
var a = c.getContext('2d');
document.body.clientWidth; // fix bug in webkit: http://qfox.nl/weblog/218
etc etc.
End of code there is script, which is used to decode code
for (Y = 0; $ = 'zxqj`_^ZWVUQONMKJIHGCA#8$ ' [Y++];)
with(_.split($)) _ = join(pop());
eval(_)
I put this firebug ... instead of eval(_) put console.log( _ )
code is
e = null;
T = function (b) {
c.width = c.height = 19 * s;
a.fillStyle = "#DB5";
a.fillRect(0, 0, c.width, c.width);
for (i = s / 2; i < c.width; i += s) a.moveTo(i, s / 2), a.lineTo(i, c.width - s / 2), a.moveTo(s / 2, i), a.lineTo(c.width - s / 2, i);
a.stroke();
b && (f = 19 * ~~(0.5 + (b.clientY - s / 2) / s) + ~~(0.5 + (b.clientX - s / 2) / s), t[f] == e && (t[f] = d, (L(f) | !(L(f + 1) & L(f - 1) & L(f + 19) & L(f - 19))) & (!m | f != n) ? "d" == b.type[5] ? (m = 0, u = f, d = !d, E(f + 1, d), E(f - 1, d), E(f + 19, d), E(f - 19, d), E(f)) : (t[f] = e, a.beginPath(), a.arc(~~(0.5 + (b.clientX - s / 2) / s) * s + s / 2, ~~ (0.5 + (b.clientY - s / 2) / s) * s + s / 2, s / 2 - 1, 0, 6.3, 1), a.strokeStyle = a.fillStyle = "rgba(0,0,0,0.3)", d && (a.fillStyle = "rgba(255,255,255,0.3)"), a.fill(), a.stroke()) : t[f] = e));
a.strokeStyle = "#000";
a.fillStyle = "#000";
for (i = s / 2 + 75; i < c.width; i += 6 * s) for (h = s / 2 + 75; h < c.width; h += 6 * s) a.beginPath(), a.arc(i, h, 2, 0, 6.3, 1), a.fill();
m && (t[n] = d, L(u) || (a.beginPath(), a.rect(n % 19 * s + s / 2 / 2, ~~ (n / 19) * s + s / 2 / 2, s / 2, s / 2), a.stroke()), t[n] = e);
for (i = t.length; i--;) t[i] != e && (a.beginPath(), a.arc(i % 19 * s + s / 2, ~~ (i / 19) * s + s / 2, s / 2 - 1, 0, 6.3, 1), a.fillStyle = "#000", t[i] && (a.fillStyle = "#FFF"), a.fill(), a.stroke())
};
E = function (b, g) {
if (!L(b, g)) {
1 == w.length && (m = 1, n = b);
for (i = w.length; i--;) t[w[i]] = e
}
};
L = function (b, g) {
w = [];
g == e && (g = t[b]);
l = function (b) {
for (i = w.length; i--;) if (w[i] == b) return;
w.push(b);
0 != (b + 1) % 19 && t[b + 1] == g && l(b + 1);
0 != b % 19 && t[b - 1] == g && l(b - 1);
t[b + 19] == g && l(b + 19);
t[b - 19] == g && l(b - 19)
};
if (g != e && g == t[b]) l(b);
else return 1;
for (i = w.length; i--;) if (0 != (w[i] + 1) % 19 && t[w[i] + 1] == e || 0 != w[i] % 19 && t[w[i] - 1] == e || 342 > w[i] && t[w[i] + 19] == e || 19 <= w[i] && t[w[i] - 19] == e) return 1;
return 0
};
s = 25;
d = m = n = 0;
c.addEventListener("mousemove", T);
c.addEventListener("mousedown", T);
t = [];
T();