<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>example_route_server/altitudeprofile.proto</filename>
    </added>
    <added>
      <filename>example_route_server/altitudeprofile_pb2.py</filename>
    </added>
    <added>
      <filename>server/altitudeprofile_pb2.py</filename>
    </added>
    <added>
      <filename>server/geopy/__init__.py</filename>
    </added>
    <added>
      <filename>server/geopy/distance.py</filename>
    </added>
    <added>
      <filename>server/geopy/geocoders.py</filename>
    </added>
    <added>
      <filename>server/geopy/util.py</filename>
    </added>
    <added>
      <filename>server/pygooglechart.py</filename>
    </added>
    <added>
      <filename>server/static/images/favicon.ico</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -1,181 +1,141 @@
-import xmlrpclib
 from os import curdir, sep
 from BaseHTTPServer import BaseHTTPRequestHandler, HTTPServer
+import urllib
+import altitudeprofile_pb2
 
 # Define example routes.
 # See http://wiki.openstreetmap.org/index.php/Route_Altitude_Profile_Example_Routes
 # Convert with:
 # s/  &lt;point id=&quot;\(.*\)&quot; lat=&quot;\(.*\)&quot; lon=&quot;\(.*\)&quot; \/&gt;/{'id' : \1, 'lat' : \2, 'lon' : \3},
 
-route1 = [\
-  {'id' : 1, 'lat' : -37.817460, 'lon' : 144.967450},
-  {'id' : 2, 'lat' : -37.806643, 'lon' : 144.962394}
-]
-
-route2 = [\
-  {'id' : 1, 'lat' : -37.794528, 'lon' : 144.989826},
-  {'id' : 2, 'lat' : -37.795407, 'lon' : 145.000048},
-  {'id' : 3, 'lat' : -37.791279, 'lon' : 145.013591},
-  {'id' : 4, 'lat' : -37.791322, 'lon' : 145.029184},
-  {'id' : 5, 'lat' : -37.790325, 'lon' : 145.039400},
-  {'id' : 6, 'lat' : -37.790672, 'lon' : 145.049962},
-  {'id' : 7, 'lat' : -37.785138, 'lon' : 145.060183},
-  {'id' : 8, 'lat' : -37.783656, 'lon' : 145.069780},
-  {'id' : 9, 'lat' : -37.780077, 'lon' : 145.078862},
-  {'id' : 10, 'lat' : -37.779669, 'lon' : 145.094697},
-  {'id' : 11, 'lat' : -37.781045, 'lon' : 145.098131},
-  {'id' : 12, 'lat' : -37.786668, 'lon' : 145.101099},
-  {'id' : 13, 'lat' : -37.790987, 'lon' : 145.105694},
-  {'id' : 14, 'lat' : -37.793852, 'lon' : 145.109749},
-  {'id' : 15, 'lat' : -37.797316, 'lon' : 145.123297},
-  {'id' : 16, 'lat' : -37.797042, 'lon' : 145.129311},
-  {'id' : 17, 'lat' : -37.798220, 'lon' : 145.141970}
-]
-
-route3 = [\
- {'id' : 1, 'lat' : -37.757051, 'lon' : 145.588828},
- {'id' : 2, 'lat' : -37.755150, 'lon' : 145.588350},
- {'id' : 3, 'lat' : -37.753840, 'lon' : 145.588630},
- {'id' : 4, 'lat' : -37.750630, 'lon' : 145.590980},
- {'id' : 5, 'lat' : -37.749408, 'lon' : 145.591019},
- {'id' : 6, 'lat' : -37.748424, 'lon' : 145.591550},
- {'id' : 7, 'lat' : -37.746884, 'lon' : 145.591616},
- {'id' : 8, 'lat' : -37.745234, 'lon' : 145.592089},
- {'id' : 9, 'lat' : -37.743067, 'lon' : 145.592000},
- {'id' : 10, 'lat' : -37.741730, 'lon' : 145.591536},
- {'id' : 11, 'lat' : -37.740398, 'lon' : 145.592294},
- {'id' : 12, 'lat' : -37.739951, 'lon' : 145.592997},
- {'id' : 13, 'lat' : -37.738844, 'lon' : 145.593178},
- {'id' : 14, 'lat' : -37.736896, 'lon' : 145.593187},
- {'id' : 15, 'lat' : -37.736136, 'lon' : 145.593429},
- {'id' : 16, 'lat' : -37.735095, 'lon' : 145.593588},
- {'id' : 17, 'lat' : -37.734520, 'lon' : 145.594400},
- {'id' : 18, 'lat' : -37.733656, 'lon' : 145.594230},
- {'id' : 19, 'lat' : -37.733499, 'lon' : 145.593709},
- {'id' : 20, 'lat' : -37.732933, 'lon' : 145.593085},
- {'id' : 21, 'lat' : -37.732407, 'lon' : 145.593070},
- {'id' : 22, 'lat' : -37.731918, 'lon' : 145.592466},
- {'id' : 23, 'lat' : -37.730634, 'lon' : 145.592464},
- {'id' : 24, 'lat' : -37.730296, 'lon' : 145.592879},
- {'id' : 25, 'lat' : -37.729805, 'lon' : 145.592849},
- {'id' : 26, 'lat' : -37.729680, 'lon' : 145.592251},
- {'id' : 27, 'lat' : -37.729440, 'lon' : 145.591970},
- {'id' : 28, 'lat' : -37.728740, 'lon' : 145.592350},
- {'id' : 29, 'lat' : -37.727986, 'lon' : 145.594543},
- {'id' : 30, 'lat' : -37.727315, 'lon' : 145.595498},
- {'id' : 31, 'lat' : -37.725260, 'lon' : 145.596140},
- {'id' : 32, 'lat' : -37.724945, 'lon' : 145.596918},
- {'id' : 33, 'lat' : -37.723526, 'lon' : 145.596857},
- {'id' : 34, 'lat' : -37.722854, 'lon' : 145.595763},
- {'id' : 35, 'lat' : -37.722560, 'lon' : 145.594690},
- {'id' : 36, 'lat' : -37.721411, 'lon' : 145.594441},
- {'id' : 37, 'lat' : -37.718561, 'lon' : 145.595810},
- {'id' : 38, 'lat' : -37.717234, 'lon' : 145.595553},
- {'id' : 39, 'lat' : -37.715411, 'lon' : 145.596968},
- {'id' : 40, 'lat' : -37.714600, 'lon' : 145.597150},
- {'id' : 41, 'lat' : -37.714658, 'lon' : 145.596673},
- {'id' : 42, 'lat' : -37.715133, 'lon' : 145.596102},
- {'id' : 43, 'lat' : -37.716074, 'lon' : 145.592537},
- {'id' : 44, 'lat' : -37.715890, 'lon' : 145.591910},
- {'id' : 45, 'lat' : -37.714920, 'lon' : 145.590900},
- {'id' : 46, 'lat' : -37.714300, 'lon' : 145.589399},
- {'id' : 47, 'lat' : -37.713340, 'lon' : 145.588830},
- {'id' : 48, 'lat' : -37.712090, 'lon' : 145.587100},
- {'id' : 49, 'lat' : -37.711530, 'lon' : 145.587240},
- {'id' : 50, 'lat' : -37.710181, 'lon' : 145.585396},
- {'id' : 51, 'lat' : -37.709587, 'lon' : 145.584916},
- {'id' : 52, 'lat' : -37.709078, 'lon' : 145.583933},
- {'id' : 53, 'lat' : -37.708300, 'lon' : 145.583453},
- {'id' : 54, 'lat' : -37.707649, 'lon' : 145.582418},
- {'id' : 55, 'lat' : -37.707180, 'lon' : 145.582000},
- {'id' : 56, 'lat' : -37.705687, 'lon' : 145.581218},
- {'id' : 57, 'lat' : -37.705231, 'lon' : 145.581301},
- {'id' : 58, 'lat' : -37.704299, 'lon' : 145.581816},
- {'id' : 59, 'lat' : -37.703990, 'lon' : 145.581650},
- {'id' : 60, 'lat' : -37.704010, 'lon' : 145.580850},
- {'id' : 61, 'lat' : -37.703184, 'lon' : 145.580396},
- {'id' : 62, 'lat' : -37.702780, 'lon' : 145.580133},
- {'id' : 63, 'lat' : -37.702760, 'lon' : 145.579432},
- {'id' : 64, 'lat' : -37.702459, 'lon' : 145.578904},
- {'id' : 65, 'lat' : -37.701463, 'lon' : 145.578541},
- {'id' : 66, 'lat' : -37.701160, 'lon' : 145.577460},
- {'id' : 67, 'lat' : -37.700844, 'lon' : 145.577135},
- {'id' : 68, 'lat' : -37.700285, 'lon' : 145.576689},
- {'id' : 69, 'lat' : -37.699702, 'lon' : 145.575396},
- {'id' : 70, 'lat' : -37.700140, 'lon' : 145.573850},
- {'id' : 71, 'lat' : -37.701910, 'lon' : 145.571290}
-]
+# Or if you have a list like:
+# 49.407810, 8.681080
+# You do: 
+# %s/\(.*\), \(.*\)/{'id' : , 'lat' : \1, 'lon' : \2}, 
+# And add the id numbers
 
-route4 = [\
- {'id' : 1, 'lat' : -30.088850, 'lon' : 145.937740},
- {'id' : 2, 'lat' : -30.094060, 'lon' : 145.936930},
- {'id' : 4, 'lat' : -30.097138, 'lon' : 145.947483},
- {'id' : 5, 'lat' : -30.097252, 'lon' : 145.947610},
- {'id' : 6, 'lat' : -30.101589, 'lon' : 145.950951},
- {'id' : 7, 'lat' : -30.108497, 'lon' : 145.957300},
- {'id' : 8, 'lat' : -30.134053, 'lon' : 145.978325},
- {'id' : 9, 'lat' : -30.141927, 'lon' : 145.980714},
- {'id' : 10, 'lat' : -30.143489, 'lon' : 145.980673},
- {'id' : 11, 'lat' : -30.145621, 'lon' : 145.979606},
- {'id' : 12, 'lat' : -30.147628, 'lon' : 145.980114},
- {'id' : 13, 'lat' : -30.152628, 'lon' : 145.985230},
- {'id' : 14, 'lat' : -30.661910, 'lon' : 146.403530},
- {'id' : 15, 'lat' : -30.666818, 'lon' : 146.403791},
- {'id' : 16, 'lat' : -30.671185, 'lon' : 146.407458},
- {'id' : 17, 'lat' : -30.677133, 'lon' : 146.417411},
- {'id' : 18, 'lat' : -31.542346, 'lon' : 147.159028},
- {'id' : 19, 'lat' : -31.559080, 'lon' : 147.188810}
+route1 = [\
+{'id' : 1, 'lat' : 49.407810, 'lon' : 8.681080},
+{'id' : 2, 'lat' : 49.407770, 'lon' : 8.684210},
+{'id' : 3, 'lat' : 49.408950, 'lon' : 8.692368},
+{'id' : 4, 'lat' : 49.407040, 'lon' : 8.692670},
+{'id' : 5, 'lat' : 49.406880, 'lon' : 8.693919},
+{'id' : 6, 'lat' : 49.407620, 'lon' : 8.694270},
+{'id' : 7, 'lat' : 49.413360, 'lon' : 8.692300},
+{'id' : 8, 'lat' : 49.414800, 'lon' : 8.692110},
+{'id' : 9, 'lat' : 49.414730, 'lon' : 8.693110}\
 ]
 
-routes = [route1, route2, route3, route4]
+routes = [route1]
 
 # ULR of altitude server:
-server_url = 'http://localhost:8000/';
-server = xmlrpclib.Server(server_url);
+#url_server_root = 'http://localhost:8080/';
+url_server_root = 'http://altitude.sprovoost.nl/';
 
 # HTTP server to serve the example routes
 class MyHandler(BaseHTTPRequestHandler):
-    def do_GET(self):
-        if self.path == &quot;/index.html&quot;:
-            f = open(curdir + sep + &quot;www&quot; + sep + &quot;index.html&quot;) 
-
-            self.send_response(200)
-            self.send_header('Content-type',	'text/html')
-            self.end_headers()
-            self.wfile.write(f.read())
-            f.close()
-            return
-
-        if self.path[:-1] == &quot;/index.html?type=xml&amp;route=&quot;:
-            route_number = int(self.path[-1])
-
-            # Get route altitude profile:
-            
-            result = server.altitude_profile(routes[route_number - 1])
-            
-            self.send_response(200)
-            self.send_header('Content-type',	'text/xml')
-            self.end_headers()
-
-            tuple_params = tuple(result)
-            self.wfile.write(xmlrpclib.dumps(tuple_params, 'route' + str(route_number)))
-            return
+  def do_GET(self):
+    if self.path == &quot;/index.html&quot;:
+      # Show all the options to the user
+
+      f = open(curdir + sep + &quot;www&quot; + sep + &quot;index.html&quot;) 
+
+      self.send_response(200)
+      self.send_header('Content-type',	'text/html')
+      self.end_headers()
+      self.wfile.write(f.read())
+      f.close()
+      return
+   
+    else: 
+      # Determine route number (substract 1 because arrays start 
+      # at 0): 
+      route_number = int(self.path[-1]) - 1
+      
+      input_type = inputTypeFromUrl(self.path)
+      output_type = outputTypeFromUrl(self.path)
+      
+      if input_type == &quot;&quot; or output_type == &quot;&quot;:
+        exit()
+
+      f = fetchResult(input_type, routes[route_number], output_type)      
+
+      if output_type == &quot;xml&quot;:
+        self.send_response(200)
+        self.send_header('Content-type',	'text/xml')
+        self.end_headers()
+      
+        s = f.read()
+        f.close()
+
+        self.wfile.write(s)
+      
+      elif output_type == &quot;gchart&quot;:
+        self.send_response(200)
+        self.send_header('Content-type',	'text/html')
+        self.end_headers()
+      
+        s = f.read()
+        f.close()
         
-        if self.path[:-1] == &quot;/index.html?type=gchart&amp;route=&quot;:
-            # Return Google Chart image
-            route_number = int(self.path[-1])
-
-            result = server.altitude_profile_gchart(routes[route_number - 1])
-            
-            self.send_response(200)
-            self.send_header('Content-type',	'text/html')
-            self.end_headers()
-
-            tuple_params = tuple(result)
-            self.wfile.write(&quot;&lt;img src='&quot; + result['gchart_url'] + &quot;' alt = '&quot; + str(route_number) + &quot;'/&gt;&quot;)
-            return
-
-        return
+        self.wfile.write('&lt;html&gt;')
+        self.wfile.write('&lt;head&gt;&lt;/head&gt;')
+        self.wfile.write('&lt;body&gt;')
+        self.wfile.write('&lt;img src=&quot;' + s +  '&quot; alt=&quot;Altitude profile&quot;/&gt;')
+
+
+def inputTypeFromUrl(url):
+  if &quot;input=protobuf&quot; in url:
+    return &quot;protobuf&quot;
+  elif &quot;input=xml&quot; in url:  
+    return &quot;xml&quot;
+  else:
+    return &quot;&quot;
+
+def outputTypeFromUrl(url):
+  if &quot;output=protobuf&quot; in url:
+    return &quot;protobuf&quot;
+  elif &quot;output=xml&quot; in url:  
+    return &quot;xml&quot;
+  elif &quot;output=gchart&quot; in url:  
+    return &quot;gchart&quot;
+  else:
+    return &quot;&quot;
+
+def fetchResult(input_type, route, output_type):
+  if input_type == &quot;protobuf&quot;:  
+    # Prepare route for transmission (Protocol Buffer)
+    route_pb = altitudeprofile_pb2.Route()
+
+    for p in route:
+      point = route_pb.point.add()
+      point.lat = p['lat']
+      point.lon = p['lon']
+
+    route_pb_string = route_pb.SerializeToString()
+
+    # Get route altitude profile:
+                
+
+    return urllib.urlopen(url_server_root + &quot;profile/xml/protobuf/&quot;, route_pb_string)
+    
+  elif input_type == &quot;xml&quot;:
+    # Let's make an xlsRouteGeometry object...
+    route_xml = &quot;&lt;?xml version=\&quot;1.0\&quot; encoding=\&quot;UTF-8\&quot;?&gt;\n&quot;
+    route_xml += &quot;&lt;xls:XLS xmlns:xls=\&quot;http://www.opengis.net/xls\&quot; xmlns:xsi=\&quot;http://www.w3.org/2001/XMLSchema-instance\&quot; xmlns:gml=\&quot;http://www.opengis.net/gml\&quot; version=\&quot;1.1\&quot; xsi:schemaLocation=\&quot;http://www.opengis.net/xls http://schemas.opengis.net/ols/1.1.0/RouteService.xsd\&quot;&gt;\n&quot;
+    route_xml += &quot;  &lt;xls:RouteGeometry&gt;\n&quot;
+    route_xml += &quot;    &lt;gml:LineString srsName=\&quot;EPSG:4326\&quot;&gt;\n&quot;
+    
+    for point in route:
+      route_xml += &quot;      &lt;gml:pos&gt;&quot;
+      route_xml += str(point['lon']) + &quot; &quot; + str(point['lat'])
+      route_xml += &quot;&lt;/gml:pos&gt;\n&quot;          
+      
+    route_xml += &quot;    &lt;/gml:LineString&gt;\n&quot;
+    route_xml += &quot;  &lt;/xls:RouteGeometry&gt;\n&quot;
+    route_xml += &quot;&lt;/xls:XLS&gt;&quot;
+
+    return urllib.urlopen(url_server_root + &quot;profile/&quot; + output_type + &quot;/xml/&quot;, route_xml)
 
 if __name__ == '__main__':
     try:</diff>
      <filename>example_route_server/server.py</filename>
    </modified>
    <modified>
      <diff>@@ -4,9 +4,26 @@
   &lt;/head&gt;
   &lt;body&gt;
     &lt;p&gt;Hi there. Pick a route to see its altitude profile. You can also view the route in Google Maps.&lt;/p&gt;
-    &lt;ul&gt;
-      &lt;li&gt;Route 1 : Downtown Heidelberg. Car route on &lt;a href=&quot;http://maps.google.com/maps?f=d&amp;hl=en&amp;geocode=17786583812122914276,49.414740,8.693260&amp;saddr=49.40779,8.681002&amp;daddr=Bergstra%C3%9Fe+%4049.414740,+8.693260&amp;mra=mi&amp;mrsp=0,1&amp;sz=15&amp;sll=49.411029,8.689027&amp;sspn=0.014128,0.037594&amp;ie=UTF8&amp;ll=49.410052,8.692503&amp;spn=0.014129,0.037594&amp;z=15&quot;&gt;Google maps&lt;/a&gt;. &lt;a href=&quot;index.html?type=ors&amp;route=1&quot;&gt;Walking route on OpenRouteService&lt;/a&gt; (xml). Altitude profile (&lt;a href=&quot;index.html?type=xml&amp;route=1&quot;&gt;xml&lt;/a&gt;, &lt;a href=&quot;index.html?type=gchart&amp;route=1&quot;&gt;Google Chart&lt;/a&gt;)
-    &lt;/ul&gt;
+    &lt;h2&gt;Route 1&lt;/h2&gt;
+    &lt;p&gt;Downtown Heidelberg. Car route on &lt;a href=&quot;http://maps.google.com/maps?f=d&amp;hl=en&amp;geocode=17786583812122914276,49.414740,8.693260&amp;saddr=49.40779,8.681002&amp;daddr=Bergstra%C3%9Fe+%4049.414740,+8.693260&amp;mra=mi&amp;mrsp=0,1&amp;sz=15&amp;sll=49.411029,8.689027&amp;sspn=0.014128,0.037594&amp;ie=UTF8&amp;ll=49.410052,8.692503&amp;spn=0.014129,0.037594&amp;z=15&quot;&gt;Google maps&lt;/a&gt;. &lt;/p&gt;
+    &lt;table border=1&gt;
+      &lt;tr&gt;&lt;td&gt;Input protocol&lt;/td&gt;&lt;td&gt;Output&lt;/td&gt;&lt;/tr&gt;
+      &lt;tr&gt;
+        &lt;td&gt;XML&lt;/td&gt;
+        &lt;td&gt;&lt;a href=&quot;index.html?input=xml&amp;output=xml&amp;route=1&quot;&gt;xml&lt;/a&gt;&lt;/td&gt; 
+        &lt;td&gt;&lt;a href=&quot;index.html?input=xml&amp;output=gchart&amp;route=1&quot;&gt;Google Chart&lt;/a&gt;&lt;/td&gt;
+      &lt;/tr&gt;
+      &lt;tr&gt;
+        &lt;td&gt;Protocol Buffers&lt;/td&gt;&lt;td&gt;Coming soon&lt;/td&gt;
+        &lt;td&gt;&lt;/td&gt;
+        &lt;td&gt;&lt;/td&gt;
+      &lt;/tr&gt;
+      &lt;tr&gt;
+        &lt;td&gt;HTTP/GET&lt;/td&gt;&lt;td&gt;Coming soon&lt;/td&gt;
+        &lt;td&gt;&lt;/td&gt;
+        &lt;td&gt;&lt;/td&gt;
+      &lt;/tr&gt;
+    &lt;/table&gt;
     &lt;p&gt;More information &lt;a href=&quot;http://wiki.openstreetmap.org/index.php/Route_altitude_profiles_SRTM&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
   &lt;/body&gt;
 &lt;/html&gt;</diff>
      <filename>example_route_server/www/index.html</filename>
    </modified>
    <modified>
      <diff>@@ -2,10 +2,10 @@
 from math import floor, ceil
 
 # Geopy: http://exogen.case.edu/projects/geopy/
-# from geopy import distance
+from geopy import distance, util
 
 # http://pygooglechart.slowchop.com/
-# from pygooglechart import XYLineChart, Axis
+from pygooglechart import XYLineChart, Axis
 
 # Google app engine ingredients:
 
@@ -14,6 +14,9 @@ import wsgiref.handlers
 
 from google.appengine.ext import db
 from google.appengine.ext import webapp
+from xml.dom import minidom
+
+#import altitudeprofile_pb2  # Protocol buffers don't work yet in App Engine
 
 ##### Database #####
 class Altitude(db.Model):
@@ -23,83 +26,117 @@ class Altitude(db.Model):
 ##### Pages ######
 class MainPage(webapp.RequestHandler):
   def get(self):
-    alts = Altitude.gql(&quot;LIMIT 10&quot;)
     self.response.out.write(&quot;&quot;&quot;
       &lt;html&gt;
         &lt;body&gt;&quot;&quot;&quot;)
-  
-    for alt in alts:
-      self.response.out.write(&quot;&lt;p&gt;&quot; + str(alt.alt) + &quot;&lt;/p&gt;&quot;)
-
-    alt = Altitude.get_by_key_name(&quot;P-19490696459&quot;)
-    self.response.out.write(&quot;&lt;p&gt;And fetch directly by keyname:&quot; + str(alt.alt) +  &quot;&lt;/p&gt;&quot;)
+    self.response.out.write(&quot;&lt;p&gt;Welcome.&lt;/p&gt;&quot;)
     self.response.out.write(&quot;&quot;&quot;       &lt;/body&gt;
       &lt;/html&gt;&quot;&quot;&quot;)
+  
+class Profile(webapp.RequestHandler):
+  def post(self, output_format, input_format):
+    # Extract the route:
+    route = []
+    if input_format == &quot;protobuf&quot;:
+      # Doesn't work in app egine yet and completely untested
+      route_pb = altitudeprofile_pb2.Route()
+      route_pb.ParseFromString(self.request.body)
+  
+      for i in range(1, len(route_pb.point) + 1):
+        point = route_pb.point[i-1]
+        route += {'id' : i, 'lat' : point.lat, 'lon' : point.lon} 
+
+    elif input_format == &quot;xml&quot;:
+      dom = minidom.parseString(self.request.body)
+      points = dom.getElementsByTagName('gml:pos') 
+
+      for i in range(1, len(points) + 1):
+        point = util.parse_geo(points[i-1].firstChild.data)
+        route.append({'id' : i, 'lat' : point[1], 'lon' : point[0]})
+
+    else:
+      # Some sort of error; we're under attack! :-)
+      route = []
+      
+
+    # Find out what the desired output is
+    if output_format == &quot;gchart&quot;:
+      url = altitude_profile_gchart(route)
+      self.response.out.write(url)
+    
+    elif output_format == &quot;xml&quot;:
+      profile = altitude_profile(route)
+      # Now return a 'nice' XML document with the result
+      xml = '&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;'
+      xml += '&lt;xls:XLS xmlns:xls=&quot;http://www.opengis.net/xls&quot; xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot; xmlns:gml=&quot;http://www.opengis.net/gml&quot; version=&quot;1.1&quot; xsi:schemaLocation=&quot;http://www.opengis.net/xls http://schemas.opengis.net/ols/1.1.0/RouteService.xsd&quot;&gt;'
+      xml += '  &lt;xls:RouteGeometry&gt;'
+      xml += '    &lt;gml:LineString srsName=&quot;EPSG:4326&quot;&gt;'
+      for point in route:
+        xml += '      &lt;gml:pos&gt;' + str(point['lon']) + &quot; &quot; + str(point['lat']) + &quot; &quot; + str(point['alt']) + '&lt;/gml:pos&gt;'
+
+      xml += '    &lt;/gml:LineString&gt;'
+      xml += '  &lt;/xls:RouteGeometry&gt;'
+      xml += '&lt;/xls:XLS&gt;'
+
+      self.response.out.write(xml)
+      
+
+def altitude_profile_gchart(route):
+    # First calculate the altitude profile
+    profile = altitude_profile(route)
+    
+    # Create gchart
+    # http://code.google.com/apis/chart/#line_charts
+    # http://pygooglechart.slowchop.com/
+
+    # For the horizontal scale, we need to know the horizontal distance 
+    # between the coordinates. First point will have coordinate 0, last 
+    # point the sum of all distances.
+    
+    # y coordinates are the altitudes.
+    
+    x_coordinates = [0]
+    y_coordinates = []  
+
+    for i in range(len(profile)-1):
+      x_coordinates.append(x_coordinates[i])
+
+      x_coordinates[i+1] += distance.distance(
+        (profile[i]['lat'],profile[i]['lon'] ),
+        (profile[i+1]['lat'],profile[i+1]['lon'] )
+      ).kilometers
+ 
+      y_coordinates.append(profile[i]['alt'])
+
+    y_coordinates.append(profile[-1]['alt'])
+
+    # Create gchart
+    # http://code.google.com/apis/chart/#line_charts
+    # http://pygooglechart.slowchop.com/
+    chart = XYLineChart(325, 200, 
+                        x_range=(0,max(x_coordinates)), y_range=(min(y_coordinates),max(y_coordinates)))
+    chart.add_data(x_coordinates)
+    chart.add_data(y_coordinates)
+    
+    chart.set_axis_labels(Axis.BOTTOM, ['0', str(max(x_coordinates))[0:4] + &quot; km&quot;])
+    chart.set_axis_labels(Axis.LEFT, [str(min(y_coordinates)) + &quot; m&quot;, str(max(y_coordinates)) + &quot; m&quot;])
 
-# Old stuff:
-
-def altitude_profile_function(route):
-    answer = []
-    # print route
-    interpolateRoute(route, 100)
-    # print route
-    for point in route:
-      point['alt'] = getAltitude(point['lat'], point['lon'])
-      # print str(point['id']) + &quot; &quot;  + str(point['alt'])
-      answer.append(point)
-
-    return answer
-
-#def altitude_profile_gchart_function(route):
-#    # First calculate the altitude profile
-#    profile = altitude_profile_function(route)
-#    
-#    # Create gchart
-#    # http://code.google.com/apis/chart/#line_charts
-#    # http://pygooglechart.slowchop.com/
-#
-#    # For the horizontal scale, we need to know the horizontal distance 
-#    # between the coordinates. First point will have coordinate 0, last 
-#    # point the sum of all distances.
-#    
-#    # y coordinates are the altitudes.
-#    
-#    x_coordinates = [0]
-#    y_coordinates = []  
-#
-#    for i in range(len(profile)-1):
-#      x_coordinates.append(x_coordinates[i])
-#
-#      x_coordinates[i+1] += distance.distance(
-#        (profile[i]['lat'],profile[i]['lon'] ),
-#        (profile[i+1]['lat'],profile[i+1]['lon'] )
-#      ).kilometers
-# 
-#      y_coordinates.append(profile[i]['alt'])
-#
-#    y_coordinates.append(profile[-1]['alt'])
-#
-#    # Create gchart
-#    # http://code.google.com/apis/chart/#line_charts
-#    # http://pygooglechart.slowchop.com/
-#    chart = XYLineChart(325, 200, 
-#                        x_range=(0,max(x_coordinates)), y_range=(min(y_coordinates),max(y_coordinates)))
-#    chart.add_data(x_coordinates)
-#    chart.add_data(y_coordinates)
-#    
-#    chart.set_axis_labels(Axis.BOTTOM, ['0', str(max(x_coordinates))[0:4] + &quot; km&quot;])
-#    chart.set_axis_labels(Axis.LEFT, [str(min(y_coordinates)) + &quot; m&quot;, str(max(y_coordinates)) + &quot; m&quot;])
-#
-#    # Return gchart url:
-#    return {'gchart_url' : chart.get_url()}
+    # Return gchart url:
+    return chart.get_url()
+    
+def altitude_profile(route):
+  answer = []
+  interpolateRoute(route, 100)
+  for point in route:
+    point['alt'] = getAltitude(point['lat'], point['lon'])
+    answer.append(point)
+  return answer
     
 ##### Database functions #####
 
 def getAltitude(lat,lon):
   pos = posFromLatLon(lat,lon)
-  sql = db.query(&quot;SELECT alt FROM altitude WHERE pos = &quot; + str(pos))
-  res = sql.getresult()
-  return res[0][0]
+  return fetchAltitudeFromDatastore(pos)
 
 ##### Helper functions ######
 
@@ -189,11 +226,23 @@ def interpolateRoute(route, n):
 
     i = i + len(pair) - 1 
 
+#### Database ####
+def fetchAltitudeFromDatastore(pos):
+  return Altitude.get_by_key_name(&quot;P&quot; + str(pos)).alt
+
+def fetchAltitudeFromPostgres(pos):
+  sql = db.query(&quot;SELECT alt FROM altitude WHERE pos = &quot; + str(pos))
+  res = sql.getresult()
+  return res[0][0]
+
 #### Main program ####
 
 def main():
   application = webapp.WSGIApplication(
-                                       [('/', MainPage)],
+                                       [
+                                        ('/', MainPage),
+                                        (r'/profile/(.*)/(.*)/', Profile)
+                                       ],
                                        debug=True)
   wsgiref.handlers.CGIHandler().run(application)
 </diff>
      <filename>server/altitude.py</filename>
    </modified>
    <modified>
      <diff>@@ -5,16 +5,23 @@ api_version: 1
 
 handlers:
 - url: /
-  script: src/altitude.py
+  script: altitude.py
+
+- url: /profile/.*
+  script: altitude.py
 
 - url: /load
-  script: src/myloader.py
+  script: myloader.py
   login: admin
 
 - url: /truncate
-  script: src/truncate.py
+  script: truncate.py
   login: admin
 
+- url: /favicon.ico
+  static_files: static/images/favicon.ico
+  upload: static/images/favicon.ico
+
 skip_files: |
  ^(.*/)?(
  (app\.yaml)|</diff>
      <filename>server/app.yaml</filename>
    </modified>
    <modified>
      <diff>@@ -81,7 +81,7 @@ if __name__ == '__main__':
       # the data row by row. sys.argv[2] represents the line number to insert.
       # You should create a script to perform the upload. Start at 1, end at 1200.
       row = int(sys.argv[2])
-      print &quot;About to make cvs for row &quot; + str(row) + &quot; of 1200...&quot;
+      print &quot;About to make csv for row &quot; + str(row) + &quot; of 1200...&quot;
       row_top = row
       row_bottom = row
       col_left = 0</diff>
      <filename>server/import-google-apps-engine.py</filename>
    </modified>
    <modified>
      <diff>@@ -9,7 +9,7 @@
 # You can abort it with ctrl+c
 
 # Get your cookie string at your-app-name.appspot.com/load
-COOKIE=&quot;--cookie=ACSID=AJKiYcG9LWK4UVV34IBnWo07ShnMveNNNEPlCbnVJlXyTcxd4lakTGwQJdrhqa33mo9zXXSSZK0kJRQJoTZ0c2Tki1UAiDh7IiHBZ1fQG3B2jVRfhgspGQQWQAqjZY1N0uK8vjUHpeUViCYRo8h8DTzsUBQpdBe7uuLfFQUkMAd-hM3qVTYHTEiR2cn8KWcGdQ9YjCTf7CTNb1ImIsTenS1mD61Hv_1tef-ixD00O1cZ8R0wUYBaBFq41GfKAAD_YaemUFr_6Hji8esBjrngDnFdkNXa_B3x_rusaHS3mizGIVdPXnlwwBESHbB_MvSWan6-qGU3scW442ELLmWvxOvr0m4UqQZwGQBDDPGEcxvaolgeuceUlSozobAMh5Yfu-MhdDzFOeYBgqAlHLZxUw4630wiQye7VbrBxdn7VXQKxlGBrjbJgxafyXaZYb8_A9LdCkOxpx6Y&quot;
+COOKIE=&quot;--cookie=ACSID=AJKiYcGKgvz9W0iA0pJg95liB4QAXL89zDouK_cBo-f74dE-9SfAZY6m1bBTJ-4QANbqWlKiUvi_-0TRTNCR3sgDW-8JE7Qj3wLcXdnXK-WBjSbphCqIPk-FbpLseuM-CXbNLIFxFuCo-SrzcRifevKQFT3DrBJU9QHI5j8HFe26t0YglqPUh7TLSvEnvycaHZXrxN0TTbAZYOThl-EknJydB0AH7k4BpGiog6m5o7ykbeHpNeRR8o37NcHHlFfkIhESpp3LHLHctb0aGGgdWKqcxxb9Im8PIUupcOMG1xMGgKs5-Jbq-sEFz8Gx2t8UtsSb3uRobluD9O2BgwDe0urWRPh6k8cClfToEjkNop2AWvvmCxoK5F6SiH6NlYOu0-5f46-7mwbucZ_q4q-nVQNofIGTRgr7UKd5w3VPcqJ3lRbZTo9cQiaBzeRN6zY70hK2Y3uBz7D-&quot;
 
 # If you use the offline data store, the cookie will look like this by defalt:
 # COOKIE=&quot;--cookie='dev_appserver_login=&quot;test@example.com:True&quot;'&quot;
@@ -52,8 +52,8 @@ do
       rm success
     else
       echo &quot;An error occured! Server probably overloaded. Let's try again...&quot;
-      echo &quot;Retry tile $a... in 30 seconds&quot;
-      sleep 30
+      echo &quot;Retry tile $a... in 5 minutes&quot;
+      sleep 300
     fi
 
   done</diff>
      <filename>server/insert.sh</filename>
    </modified>
  </modified>
  <removed type="array">
    <removed>
      <filename>example_route_server/example_request.xml</filename>
    </removed>
  </removed>
  <parents type="array">
    <parent>
      <id>277f2e06179d57175c29d1f6274684892742e684</id>
    </parent>
  </parents>
  <author>
    <name>Sjors</name>
    <email>sjors@sprovoost.nl</email>
  </author>
  <url>http://github.com/Sjors/openstreetmap-route-altitude-profile/commit/2cce8cb42ea77d38dfae2903973e886723e8cb99</url>
  <id>2cce8cb42ea77d38dfae2903973e886723e8cb99</id>
  <committed-date>2008-07-09T05:09:49-07:00</committed-date>
  <authored-date>2008-07-09T05:09:49-07:00</authored-date>
  <message>XML input with XML and Google Chart output work in Google AppEngine\!</message>
  <tree>e80bcf81f330114e18ae136b1100c16bc309c8e5</tree>
  <committer>
    <name>Sjors</name>
    <email>sjors@sprovoost.nl</email>
  </committer>
</commit>
