Converted encoding from ISO8859-15 to UTF-8.
[philipp/winterrodeln/wrpylib.git] / wrpylib / wrmwcache.py
index d8c2caec738ee33a5c254f61002a98b91b37aa35..cb0608341344dc230fe27fe05f89f99992755f7f 100644 (file)
@@ -1,12 +1,14 @@
-#!/usr/bin/python2.6
+#!/usr/bin/python3.4
 # -*- coding: iso-8859-15 -*-
 # $Id$
 # $HeadURL$
 """Contains functions that maintain/update the cache tables."""
 from sqlalchemy import schema
 from sqlalchemy.sql import select
 # -*- coding: iso-8859-15 -*-
 # $Id$
 # $HeadURL$
 """Contains functions that maintain/update the cache tables."""
 from sqlalchemy import schema
 from sqlalchemy.sql import select
+from sqlalchemy.sql.expression import func as sqlfunc
+from osgeo import ogr
 import formencode
 import formencode
-from wrpylib import mwdb, wrmwdb, mwmarkup, wrmwmarkup
+from wrpylib import mwdb, wrmwdb, mwmarkup, wrmwmarkup, wrvalidators
 
 
 class UpdateCacheError(RuntimeError):
 
 
 class UpdateCacheError(RuntimeError):
@@ -18,8 +20,7 @@ def update_wrsledruncache(connection):
     is raised. No other exception type should be raised under normal circumstances.
     
     >>> from sqlalchemy.engine import create_engine
     is raised. No other exception type should be raised under normal circumstances.
     
     >>> from sqlalchemy.engine import create_engine
-    >>> engine = create_engine('mysql://philipp@localhost:3306/philipp_winterrodeln_wiki?charset=utf8&use_unicode=0')
-    >>> # see: https://sourceforge.net/tracker/?func=detail&aid=2837134&group_id=22307&atid=374932
+    >>> engine = create_engine('mysql://philipp@localhost:3306/philipp_winterrodeln_wiki?charset=utf8&use_unicode=1')
     >>> update_wrsledruncache(engine.connect())
     """
     metadata = schema.MetaData()
     >>> update_wrsledruncache(engine.connect())
     """
     metadata = schema.MetaData()
@@ -32,7 +33,7 @@ def update_wrsledruncache(connection):
     transaction = connection.begin()
 
     # Query all sled runs
     transaction = connection.begin()
 
     # Query all sled runs
-    q = select([page, categorylinks, revision, text], (page.c.page_latest==revision.c.rev_id) & (text.c.old_id==revision.c.rev_text_id) & (categorylinks.c.cl_from==page.c.page_id) & (categorylinks.c.cl_to==u'Rodelbahn'))
+    q = select([page, categorylinks, revision, text], (page.c.page_latest==revision.c.rev_id) & (text.c.old_id==revision.c.rev_text_id) & (categorylinks.c.cl_from==page.c.page_id) & (categorylinks.c.cl_to=='Rodelbahn'))
     sledrun_pages = connection.execute(q)
     # Original SQL:
     # sql = u"select page_id, rev_id, old_id, page_title, old_text, 'In_Arbeit' in (select cl_to from categorylinks where cl_from=page_id) as under_construction from page, revision, text, categorylinks where page_latest=rev_id and old_id=rev_text_id and cl_from=page_id and cl_to='Rodelbahn' order by page_title"
     sledrun_pages = connection.execute(q)
     # Original SQL:
     # sql = u"select page_id, rev_id, old_id, page_title, old_text, 'In_Arbeit' in (select cl_to from categorylinks where cl_from=page_id) as under_construction from page, revision, text, categorylinks where page_latest=rev_id and old_id=rev_text_id and cl_from=page_id and cl_to='Rodelbahn' order by page_title"
@@ -47,11 +48,12 @@ def update_wrsledruncache(connection):
             start, end, sledrun = wrmwmarkup.rodelbahnbox_to_sledrun(sledrun_page.old_text)
             sledrun.page_id = sledrun_page.page_id
             sledrun.page_title = sledrun_page.page_title
             start, end, sledrun = wrmwmarkup.rodelbahnbox_to_sledrun(sledrun_page.old_text)
             sledrun.page_id = sledrun_page.page_id
             sledrun.page_title = sledrun_page.page_title
-            sledrun.under_construction = connection.execute(select([categorylinks], (categorylinks.c.cl_from==sledrun_page.page_id) & (categorylinks.c.cl_to == u'In_Arbeit')).alias('x').count()).fetchone()[0] > 0 # It would be better to do this in the query above
+            sledrun.name_url = wrvalidators.sledrun_page_title_to_pretty_url(sledrun_page.page_title)
+            sledrun.under_construction = connection.execute(select([categorylinks], (categorylinks.c.cl_from==sledrun_page.page_id) & (categorylinks.c.cl_to == 'In_Arbeit')).alias('x').count()).fetchone()[0] > 0 # It would be better to do this in the query above
             connection.execute(wrsledruncache.insert(sledrun.__dict__))
         except (RuntimeError, formencode.Invalid) as e:
             transaction.rollback()
             connection.execute(wrsledruncache.insert(sledrun.__dict__))
         except (RuntimeError, formencode.Invalid) as e:
             transaction.rollback()
-            error_msg = u"Error at sled run '{0}': {1}".format(sledrun_page.page_title, unicode(e))
+            error_msg = "Error at sled run '{0}': {1}".format(sledrun_page.page_title, str(e))
             raise UpdateCacheError(error_msg, sledrun_page.page_title, e)
     transaction.commit()
 
             raise UpdateCacheError(error_msg, sledrun_page.page_title, e)
     transaction.commit()
 
@@ -61,8 +63,7 @@ def update_wrinncache(connection):
     is raised. No other exception type should be raised under normal circumstances.
     
     >>> from sqlalchemy.engine import create_engine
     is raised. No other exception type should be raised under normal circumstances.
     
     >>> from sqlalchemy.engine import create_engine
-    >>> engine = create_engine('mysql://philipp@localhost:3306/philipp_winterrodeln_wiki?charset=utf8&use_unicode=0')
-    >>> # see: https://sourceforge.net/tracker/?func=detail&aid=2837134&group_id=22307&atid=374932
+    >>> engine = create_engine('mysql://philipp@localhost:3306/philipp_winterrodeln_wiki?charset=utf8&use_unicode=1')
     >>> update_wrinncache(engine.connect())
     """
     metadata = schema.MetaData()
     >>> update_wrinncache(engine.connect())
     """
     metadata = schema.MetaData()
@@ -75,7 +76,7 @@ def update_wrinncache(connection):
     transaction = connection.begin()
 
     # Query all inns
     transaction = connection.begin()
 
     # Query all inns
-    q = select([page, categorylinks, revision, text], (page.c.page_latest==revision.c.rev_id) & (text.c.old_id==revision.c.rev_text_id) & (categorylinks.c.cl_from==page.c.page_id) & (categorylinks.c.cl_to==u'Gasthaus'))
+    q = select([page, categorylinks, revision, text], (page.c.page_latest==revision.c.rev_id) & (text.c.old_id==revision.c.rev_text_id) & (categorylinks.c.cl_from==page.c.page_id) & (categorylinks.c.cl_to=='Gasthaus'))
     inn_pages = connection.execute(q)
         
     # Delete all existing entries in wrinncache
     inn_pages = connection.execute(q)
         
     # Delete all existing entries in wrinncache
@@ -88,11 +89,11 @@ def update_wrinncache(connection):
             start, end, inn = wrmwmarkup.gasthausbox_to_inn(inn_page.old_text)
             inn.page_id = inn_page.page_id
             inn.page_title = inn_page.page_title
             start, end, inn = wrmwmarkup.gasthausbox_to_inn(inn_page.old_text)
             inn.page_id = inn_page.page_id
             inn.page_title = inn_page.page_title
-            inn.under_construction = connection.execute(select([categorylinks], (categorylinks.c.cl_from==inn_page.page_id) & (categorylinks.c.cl_to == u'In_Arbeit')).alias('x').count()).fetchone()[0] > 0 # It would be better to do this in the query above
+            inn.under_construction = connection.execute(select([categorylinks], (categorylinks.c.cl_from==inn_page.page_id) & (categorylinks.c.cl_to == 'In_Arbeit')).alias('x').count()).fetchone()[0] > 0 # It would be better to do this in the query above
             connection.execute(wrinncache.insert(inn.__dict__))
         except (RuntimeError, formencode.Invalid) as e:
             transaction.rollback()
             connection.execute(wrinncache.insert(inn.__dict__))
         except (RuntimeError, formencode.Invalid) as e:
             transaction.rollback()
-            error_msg = u"Error as inn '{0}': {1}".format(inn_page.page_title, unicode(e))
+            error_msg = "Error as inn '{0}': {1}".format(inn_page.page_title, str(e))
             raise UpdateCacheError(error_msg, inn_page.page_title, e)
     transaction.commit()
 
             raise UpdateCacheError(error_msg, inn_page.page_title, e)
     transaction.commit()
 
@@ -105,7 +106,6 @@ def update_wrreportcache(connection, page_id=None):
 
     >>> from sqlalchemy.engine import create_engine
     >>> engine = create_engine('mysql://philipp@localhost:3306/philipp_winterrodeln_wiki?charset=utf8&use_unicode=1')
 
     >>> from sqlalchemy.engine import create_engine
     >>> engine = create_engine('mysql://philipp@localhost:3306/philipp_winterrodeln_wiki?charset=utf8&use_unicode=1')
-    >>> # see: https://sourceforge.net/tracker/?func=detail&aid=2837134&group_id=22307&atid=374932
     >>> update_wrreportcache(engine.connect())
     """
     metadata = schema.MetaData()
     >>> update_wrreportcache(engine.connect())
     """
     metadata = schema.MetaData()
@@ -144,11 +144,9 @@ def update_wrmapcache(connection):
     is raised. No other exception type should be raised under normal circumstances.
     
     >>> from sqlalchemy.engine import create_engine
     is raised. No other exception type should be raised under normal circumstances.
     
     >>> from sqlalchemy.engine import create_engine
-    >>> engine = create_engine('mysql://philipp@localhost:3306/philipp_winterrodeln_wiki?charset=utf8&use_unicode=0')
-    >>> # or: engine = create_engine('mysql://philipp@localhost:3306/philipp_winterrodeln_wiki?charset=utf8&use_unicode=0&passwd=XXXXX')
-    >>> # see: https://sourceforge.net/tracker/?func=detail&aid=2837134&group_id=22307&atid=374932
-    >>> connection = engine.connect()
-    >>> update_wrmapcache(connection)
+    >>> engine = create_engine('mysql://philipp@localhost:3306/philipp_winterrodeln_wiki?charset=utf8&use_unicode=1')
+    >>> # or: engine = create_engine('mysql://philipp@localhost:3306/philipp_winterrodeln_wiki?charset=utf8&use_unicode=1&passwd=XXXXX')
+    >>> update_wrmapcache(engine.connect())
     """
     metadata = schema.MetaData()
     page = mwdb.page_table(metadata)
     """
     metadata = schema.MetaData()
     page = mwdb.page_table(metadata)
@@ -159,7 +157,7 @@ def update_wrmapcache(connection):
     transaction = connection.begin()
 
     # Query all sledruns
     transaction = connection.begin()
 
     # Query all sledruns
-    q = select([page, categorylinks, revision, text], (page.c.page_latest==revision.c.rev_id) & (text.c.old_id==revision.c.rev_text_id) & (categorylinks.c.cl_from==page.c.page_id) & (categorylinks.c.cl_to==u'Rodelbahn'))
+    q = select([page, categorylinks, revision, text], (page.c.page_latest==revision.c.rev_id) & (text.c.old_id==revision.c.rev_text_id) & (categorylinks.c.cl_from==page.c.page_id) & (categorylinks.c.cl_to=='Rodelbahn'))
     sledrun_pages = connection.execute(q)
     # Original SQL:
     # sql = u"select page_id, rev_id, old_id, page_title, old_text, 'In_Arbeit' in (select cl_to from categorylinks where cl_from=page_id) as under_construction from page, revision, text, categorylinks where page_latest=rev_id and old_id=rev_text_id and cl_from=page_id and cl_to='Rodelbahn' order by page_title"
     sledrun_pages = connection.execute(q)
     # Original SQL:
     # sql = u"select page_id, rev_id, old_id, page_title, old_text, 'In_Arbeit' in (select cl_to from categorylinks where cl_from=page_id) as under_construction from page, revision, text, categorylinks where page_latest=rev_id and old_id=rev_text_id and cl_from=page_id and cl_to='Rodelbahn' order by page_title"
@@ -172,30 +170,76 @@ def update_wrmapcache(connection):
     # Refill wrmappointcache and wrmappathcache tables
     for sledrun_page in sledrun_pages:
         try: 
     # Refill wrmappointcache and wrmappathcache tables
     for sledrun_page in sledrun_pages:
         try: 
-            result = mwmarkup.parse_googlemap(sledrun_page.old_text)
-            if not result is None:
-                center, zoom, coords, paths = result
+            start, content, endtag, end = mwmarkup.find_tag(sledrun_page.old_text, 'wrmap')
+            if content is None:
+                continue
+            geojson = wrmwmarkup.parse_wrmap(sledrun_page.old_text[start:end])
+
+            for feature in geojson['features']:
+                properties = feature['properties']
+                coordinates = feature['geometry']['coordinates']
+
                 # Points
                 # Points
-                for coord in coords:
-                    lon, lat, point_type, label = coord
-                    point_types = {u'Gasthaus': u'hut', u'Haltestelle': u'busstop', u'Parkplatz': u'carpark', u'Achtung': u'warning'}
-                    if not point_type is None:
-                        if not point_types.has_key(point_type): raise RuntimeError(u'Unknown point type {0}'.format(point_type))
-                        point_type = point_types[point_type]
-                        sql = u'insert into wrmappointcache (page_id, type, point, label) values (%s, %s, POINT(%s, %s), %s)'
-                        connection.execute(sql, (sledrun_page.page_id, point_type, lon, lat, label))
+                if properties['type'] in wrmwmarkup.WRMAP_POINT_TYPES:
+                    lon, lat = coordinates
+                    label = properties.get('name')
+                    point_types = {'gasthaus': 'hut', 'haltestelle': 'busstop', 'parkplatz': 'carpark', 'achtung': 'warning', 'foto': 'photo', 'verleih': 'rental', 'punkt': 'point'}
+                    point_type = point_types[properties['type']]
+                    sql = 'insert into wrmappointcache (page_id, type, point, label) values (%s, %s, POINT(%s, %s), %s)'
+                    connection.execute(sql, (sledrun_page.page_id, point_type, lon, lat, label))
+
                 # Paths
                 # Paths
-                for path_type, coords in paths:
-                    path_type = path_type.lower()
-                    path_types = {u'6#ff014e9a': u'sledrun', u'6#ffe98401': u'walkup', u'6#ff7f7fff': u'alternative', u'3#ff000000': u'lift'}
-                    if not path_types.has_key(path_type): raise RuntimeError(u'Unknown path type {0}'.format(path_type))
-                    path_type = path_types[path_type]
-                    path = u", ".join(["{0} {1}".format(lon, lat) for lon, lat, symbol, title in coords])
-                    path = u'LineString({0})'.format(path)
-                    sql = u'insert into wrmappathcache (path, page_id, type) values (GeomFromText(%s), %s, %s)'
+                elif properties['type'] in wrmwmarkup.WRMAP_LINE_TYPES:
+                    path_types = {'rodelbahn': 'sledrun', 'gehweg': 'walkup', 'alternative': 'alternative', 'lift': 'lift', 'anfahrt': 'recommendedcarroute', 'linie': 'line'}
+                    path_type = path_types[properties['type']]
+                    path = ", ".join(["{0} {1}".format(lon, lat) for lon, lat in coordinates])
+                    path = 'LineString({0})'.format(path)
+                    if path_type == 'recommendedcarroute': continue
+                    sql = 'insert into wrmappathcache (path, page_id, type) values (GeomFromText(%s), %s, %s)'
                     connection.execute(sql, (path, sledrun_page.page_id, path_type))
                     connection.execute(sql, (path, sledrun_page.page_id, path_type))
+
+                else:
+                    raise RuntimeError('Unknown feature type {0}'.format(properties['type']))
         except RuntimeError as e:
         except RuntimeError as e:
-            error_msg = u"Error at sledrun '{0}': {1}".format(sledrun_page.page_title, unicode(e))
+            error_msg = "Error at sledrun '{0}': {1}".format(sledrun_page.page_title, str(e))
             transaction.rollback()
             raise UpdateCacheError(error_msg, sledrun_page.page_title, e)
     transaction.commit()
             transaction.rollback()
             raise UpdateCacheError(error_msg, sledrun_page.page_title, e)
     transaction.commit()
+
+
+def update_wrregioncache(connection):
+    """Updates the wrregioncache table from the wiki.
+    It relays on the table wrsledruncache to be up-to-date.
+    No exceptions should be raised under normal circumstances.
+    
+    >>> from sqlalchemy.engine import create_engine
+    >>> engine = create_engine('mysql://philipp@localhost:3306/philipp_winterrodeln_wiki?charset=utf8&use_unicode=1')
+    >>> # or: engine = create_engine('mysql://philipp@localhost:3306/philipp_winterrodeln_wiki?charset=utf8&use_unicode=1&passwd=XXXXX')
+    >>> update_wrregioncache(engine.connect())
+    """
+    metadata = schema.MetaData()
+    wrregion = wrmwdb.wrregion_table(metadata)
+    wrsledruncache = wrmwdb.wrsledruncache_table(metadata)
+    wrregioncache = wrmwdb.wrregioncache_table(metadata)
+
+    transaction = connection.begin()
+
+    # Delete all existing entries in wrregioncache
+    # We rely on transactions MySQL InnoDB
+    connection.execute(wrregioncache.delete())
+    
+    # Query all combinations of sledruns and regions
+    sel = select([wrregion.c.id.label('region_id'), sqlfunc.AsWKB(wrregion.c.border).label('border'), wrsledruncache.c.page_id, wrsledruncache.c.position_longitude, wrsledruncache.c.position_latitude], sqlfunc.contains(wrregion.c.border, sqlfunc.point(wrsledruncache.c.position_longitude, wrsledruncache.c.position_latitude)))
+    ins = wrregioncache.insert()
+
+    # Refill wrregioncache
+    point = ogr.Geometry(ogr.wkbPoint)
+    result = connection.execute(sel)
+    for row in result:
+        point.SetPoint(0, row.position_longitude, row.position_latitude)
+        if point.Within(ogr.CreateGeometryFromWkb(row.border)):
+            connection.execute(ins.values(region_id=row.region_id, page_id=row.page_id))
+
+    # commit
+    transaction.commit()
+