<?php | |
/* | |
* GeoPo Encode in PHP | |
* @author : Shintaro Inagaki | |
* @param $location (Array) | |
* @return $geopo (String) | |
*/ | |
function geopoEncode($lat, $lng) { | |
// 64characters (number + big and small letter + hyphen + underscore) | |
$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"; | |
$geopo = ""; | |
$scale = 7; | |
// Change a degree measure to a decimal number | |
$lat = ($lat + 90) / 180 * pow(8, 10); | |
$lng = ($lng + 180) / 360 * pow(8, 10); | |
// Compute a GeoPo code from head and concatenate | |
for($i = 0; $i < $scale; $i++) { | |
$geopo .= substr($chars, floor($lat / pow(8, 9 - $i) % 8) + floor($lng / pow(8, 9 - $i) % 8) * 8, 1); | |
} | |
return $geopo; | |
} | |
/* | |
* GeoPo Decode in PHP | |
* @author : Shintaro Inagaki | |
* @param $geopo (String) | |
* @return $location (Array) | |
*/ | |
function geopoDecode($geopo) { | |
// 64characters (number + big and small letter + hyphen + underscore) | |
$chars = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-_"; | |
// Array for geolocation | |
$location = array (); | |
for ($i = 0; $i < strlen($geopo); $i++) { | |
// What number of character that equal to a GeoPo code (0-63) | |
$order = strpos($chars, substr($geopo, $i, 1)); | |
// Lat/Lng plus geolocation value of scale | |
$location['lat'] = $location['lat'] + floor($order % 8) * pow(8, 9 - $i); | |
$location['lng'] = $location['lng'] + floor($order / 8) * pow(8, 9 - $i); | |
} | |
// Change a decimal number to a degree measure, and plus revised value that shift center of area | |
$location['lat'] = $location['lat'] * 180 / pow(8, 10) + 180 / pow(8, strlen($geopo)) / 2 - 90; | |
$location['lng'] = $location['lng'] * 360 / pow(8, 10) + 360 / pow(8, strlen($geopo)) / 2 - 180; | |
$location['scale'] = strlen($geopo); | |
return $location; | |
} | |
$conn = pg_connect("dbname=bus user=postgres password=snmc"); | |
if (!$conn) { | |
echo "An error occured.\n"; | |
exit; | |
} | |
$xml = simplexml_load_file("04-locatebetweenpoints.osm"); | |
/* Access the <rating> nodes of the first movie. | |
* Output the rating scale, too. */ | |
foreach ($xml->node as $node) { | |
$geoPo = geopoEncode((float)$node['lat'],(float)$node['lon']); | |
$node['lat'] = (int) ((float)$node['lat']*10000000); | |
$node['lon'] = (int) ((float)$node['lon']*10000000); | |
echo($node['lat'].",".$node['lon']."=$geoPo<br>"); | |
$sql = "INSERT INTO stops (geohash, lat, lng) VALUES('$geoPo','{$node['lat']}','{$node['lon']}')"; | |
$result = pg_query($conn, $sql); | |
if (!$result) { | |
echo("Error in SQL query: " . pg_last_error() ."<br>\n"); | |
} | |
flush(); | |
} | |
?> | |
<?php | <?php |
date_default_timezone_set('Australia/ACT'); | date_default_timezone_set('Australia/ACT'); |
$APIurl = "http://localhost:8765"; | |
function isDebug() | |
{ | |
return true; | |
} | |
function isFastDevice() { | |
return true; | |
} | |
function include_header($pageTitle) { | |
// if (isDebug()) // set php error level high | |
echo ' | |
<!DOCTYPE html> | |
<html> | |
<head> | |
<title>bus.lambdacomplex.org - '.$pageTitle.'</title> | |
<link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a1/jquery.mobile-1.0a1.min.css" /> | |
<script src="http://code.jquery.com/jquery-1.4.3.min.js"></script><script type="text/javascript" | |
src="http://code.jquery.com/mobile/1.0a1/jquery.mobile-1.0a1.min.js"></script> | |
<script type="text/javascript" src="docs/docs.js"></script> | |
</head> | |
<body> | |
<div data-role="page"> | |
<div data-role="header"> | |
<h1>'.$pageTitle.'</h1> | |
</div><!-- /header --> | |
<div data-role="content"> '; | |
} | |
function include_footer() | |
{ | |
echo '</div>'; | |
} | |
function service_period() | function service_period() |
{ | { |
switch (date('w')){ | switch (date('w')){ |
case 0: | case 0: |
return 'sunday'; | return 'sunday'; |
case 6: | case 6: |
return 'saturday'; | return 'saturday'; |
default: | default: |
return 'weekday'; | return 'weekday'; |
} | } |
} | } |
function midnight_seconds() | |
{ | |
// from http://www.perturb.org/display/Perlfunc__Seconds_Since_Midnight.html | |
$secs = (date("G") * 3600) + (date("i") * 60) + date("s"); | |
return $secs; | |
} | |
function midnight_seconds_to_time($seconds) | |
{ | |
$midnight = mktime (0, 0, 0, date("n"), date("j"), date("Y")); | |
return date("h:ia",$midnight+$seconds); | |
} | |
function getPage($url) | |
{ | |
$ch = curl_init($url); | |
curl_setopt( $ch, CURLOPT_RETURNTRANSFER, 1 ); | |
curl_setopt( $ch, CURLOPT_HEADER, 0 ); | |
$page = curl_exec($ch); | |
curl_close($ch); | |
return $page; | |
} | |
function array_flatten($a,$f=array()){ | |
if(!$a||!is_array($a))return ''; | |
foreach($a as $k=>$v){ | |
if(is_array($v))$f=array_flatten($v,$f); | |
else $f[$k]=$v; | |
} | |
return $f; | |
} | |
?> | ?> |
<?php | |
include('common.inc.php'); | |
?> | |
<!doctype html> | <!doctype html> |
<html> | <html> |
<head> | <head> |
<meta charset="UTF-8" /> | <meta charset="UTF-8" /> |
<title>jQTouch β</title> | <title>bus.lambdacomplex.org</title> |
<style type="text/css" media="screen">@import "jqtouch/jqtouch.min.css";</style> | <link rel="stylesheet" href="http://code.jquery.com/mobile/1.0a1/jquery.mobile-1.0a1.min.css" /> |
<style type="text/css" media="screen">@import "themes/jqt/theme.min.css";</style> | <script src="http://code.jquery.com/jquery-1.4.3.min.js"></script> |
<script src="jqtouch/jquery.1.3.2.min.js" type="text/javascript" charset="utf-8"></script> | <script src="http://code.jquery.com/mobile/1.0a1/jquery.mobile-1.0a1.min.js"></script> |
<script src="jqtouch/jqtouch.min.js" type="application/x-javascript" charset="utf-8"></script> | <!-- <script src="jqtouch/extensions/jqt.location.js" type="application/x-javascript" charset="utf-8"></script> --> |
<script src="extensions/jqt.location.js" type="application/x-javascript" charset="utf-8"></script> | |
<script type="text/javascript" charset="utf-8"> | <!-- <script type="text/javascript" charset="utf-8"> |
var jQT = new $.jQTouch({ | |
icon: 'jqtouch.png', | |
addGlossToIcon: false, | |
startupScreen: 'jqt_startup.png', | |
statusBar: 'black', | |
preloadImages: [ | |
'themes/jqt/img/back_button.png', | |
'themes/jqt/img/back_button_clicked.png', | |
'themes/jqt/img/button_clicked.png', | |
'themes/jqt/img/grayButton.png', | |
'themes/jqt/img/whiteButton.png', | |
'themes/jqt/img/loading.gif' | |
] | |
}); | |
$(function(){ | $(function(){ |
function setDisplay(text) { | function setDisplay(text) { |
$('.info').empty().append(text) | $('.latlng').empty().append(text) |
} | } |
// We pass "updateLocation" a callback function, | // We pass "updateLocation" a callback function, |
// to run once we have the coordinates. | // to run once we have the coordinates. |
// We also set it to a variable, so we can know | // We also set it to a variable, so we can know |
// right away if it's working or not | // right away if it's working or not |
var lookup = jQT.updateLocation(function(coords){ | var lookup = jQT.updateLocation(function(coords){ |
if (coords) { | if (coords) { |
setDisplay('Latitude: ' + coords.latitude + '<br />Longitude: ' + coords.longitude); | setDisplay('Latitude: ' + coords.latitude + '<br />Longitude: ' + coords.longitude); |
$('.nearby').empty().append('<a href="list.php?lat=' + coords.latitude + '&lng=' + coords.longitude + '">Nearby List</a>'); | $('.nearby').empty().append('<a href="list.php?lat=' + coords.latitude + '&lng=' + coords.longitude + '">Nearby List</a>'); |
} else { | } else { |
setDisplay('Device not capable of geo-location.'); | setDisplay('Device not capable of geo-location.'); |
} | } |
}); | }); |
if (lookup) { | if (lookup) { |
setDisplay('Looking up location…'); | setDisplay('Looking up location…'); |
} | } |
}); | }); |
// Some sample Javascript functions: | </script> --> |
$(function(){ | |
$('a[target="_blank"]').click(function() { | |
if (confirm('This link opens in a new window.')) { | |
return true; | |
} else { | |
$(this).removeClass('active'); | |
return false; | |
} | |
}); | |
// Page animation callback events | |
$('#pageevents'). | |
bind('pageAnimationStart', function(e, info){ | |
$(this).find('.info').append('Started animating ' + info.direction + '… '); | |
}). | |
bind('pageAnimationEnd', function(e, info){ | |
$(this).find('.info').append(' finished animating ' + info.direction + '.<br /><br />'); | |
}); | |
// Page animations end with AJAX callback event, example 1 (load remote HTML only first time) | |
$('#callback').bind('pageAnimationEnd', function(e, info){ | |
if (!$(this).data('loaded')) { // Make sure the data hasn't already been loaded (we'll set 'loaded' to true a couple lines further down) | |
$(this).append($('<div>Loading</div>'). // Append a placeholder in case the remote HTML takes its sweet time making it back | |
load('ajax.html .info', function() { // Overwrite the "Loading" placeholder text with the remote HTML | |
$(this).parent().data('loaded', true); // Set the 'loaded' var to true so we know not to re-load the HTML next time the #callback div animation ends | |
})); | |
} | |
}); | |
// Orientation callback event | |
$('body').bind('turn', function(e, data){ | |
$('#orient').html('Orientation: ' + data.orientation); | |
}); | |
}); | |
</script> | |
</head> | </head> |
<body> | <body> |
<div id="home" class="current"> | <div data-role="page" data-theme="b" id="jqm-home"> |
<div class="toolbar"> | <div id="jqm-homeheader"> |
<h1>jQTouch</h1> | <p>bus.lambdacomplex.org</p> |
<a class="button slideup" id="infoButton" href="#about">About</a> | </div> |
</div> | <div data-role="content"> |
<ul class="rounded"> | <ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b"> |
<li class="arrow"><a href="#ui">User Interface</a> <small class="counter">4</small></li> | <li data-role="list-divider">Stops</li> |
<li class="arrow"><a href="list.php">All stops List</a></li> | <li><a href="stopList.php">All stops List</a></li> |
<li class="arrow nearby">Nearby List</li> | <li class="nearby"><a href="">Nearby List</a></li> |
<li class="arrow"><a href="list.php">Favourites List</a></li> | <li><a href="stopList.php">Favourites List</a></li> |
</ul> | |
<ul data-role="listview" data-inset="true" data-theme="c" data-dividertheme="b"> | |
<li data-role="list-divider">Routes</li> | |
<li><a href="routeList.php">All Routes List</a></li> | |
<li class="nearby"><a href="">Nearby List</a></li> | |
<li><a href="routeList.php">Favourites List</a></li> | |
</ul> | </ul> |
<div class="info"> | <div class="info"> |
<p>Add this page to your home screen to view the custom icon, startup screen, and full screen mode.</p> | <p class="latlng"></p> |
Time: <?php echo date("H:m"); ?> <br> | |
Service Period: <?php echo ucwords(service_period()); ?> | |
</div> | </div> |
</div> | </div> |
</body> | </div> |
</body> | |
</html> | </html> |
# input location (via GPS or favourites or search) and destination (via searchable list, optional) | |
# http://10.0.1.153:8765/json/boundboxstops?n=-35.27568499917103&e=149.1346514225006&s=-35.279495003493516 | |
&w=149.12622928619385&limit=50 | |
# http://10.0.1.153:8765/json/stoptrips?stop=43&time=64440 # recursively call to show all services nearby, sort by distance, need to filter by service period | |
# Hey, can pick destination again from a list filtered to places these stops go if you're curious! | |
# http://10.0.1.153:8765/json/tripstoptimes?trip=2139 # Can recursively call and parse based on intended destination to show ETA | |
# http://10.0.1.153:8765/json/triprows?trip=2139 # For pretty maps | |
have to do | |
/usr/sbin/setsebool -P httpd_can_network_connect=1 | |
on fedora | |
might need http://forum.jquery.com/topic/google-maps-inside-jquery-mobile | |
some extras | |
/json/routes = all routes | |
/json/neareststops?lat/lng/number | |
TODO | TODO |
Destinations | |
Favourites | |
OOP stops/routes | |
Stop sorting/search-filter | |
<?php | |
include('common.inc.php'); | |
include_header("Routes"); | |
/* data-filter="true">'; | |
echo "<script> $('#routeList').listnav({prefixes: ['to'] }); </script>";*/ | |
echo ' <ul data-role="listview">'; | |
$url = $APIurl."/json/routes"; | |
$contents = json_decode(getPage($url)); | |
foreach ($contents as $key => $row) { | |
$routeDestinations[$row[2]][] = $row; | |
} | |
foreach ($routeDestinations as $destination => $routes) | |
{ | |
echo '<li>'.$destination."... <ul>\n"; | |
foreach($routes as $row) { | |
echo '<li>'.$row[1].' <a href="route.php?routeid='.$row[0].'">'.$row[2]."</a></li>\n"; | |
} | |
echo "</ul></li>\n"; | |
} | |
echo "</ul>\n"; | |
/* | |
<div data-role="footer" data-id="foo1" data-position="fixed"> | |
<div data-role="navbar"> | |
<ul> | |
<li><a href="footer-persist-a.html" class="ui-btn-active">Friends</a></li> | |
<li><a href="footer-persist-b.html">Albums</a></li> | |
<li><a href="footer-persist-c.html">Emails</a></li> | |
</ul> | |
</div><!-- /navbar --> | |
*/ | |
include_footer(); | |
?> | |
#!/usr/bin/python2.5 | |
# Copyright (C) 2007 Google Inc. |