Log geometry to DB, track if geometry has been modified

This commit is contained in:
Liam Steckler 2024-11-23 17:07:02 -08:00
parent 2f9c408751
commit 769e835411
2 changed files with 35 additions and 36 deletions

View file

@ -1,4 +1,5 @@
from shapely import MultiPolygon, Polygon from shapely import MultiPolygon, Polygon, Geometry, to_wkb, from_wkb
from sqlalchemy.types import TypeDecorator, LargeBinary
def convert_outage_geometry(event) -> MultiPolygon: def convert_outage_geometry(event) -> MultiPolygon:
@ -9,3 +10,21 @@ def convert_outage_geometry(event) -> MultiPolygon:
for ring in event["polygons"]["rings"]: for ring in event["polygons"]["rings"]:
polygon_list.append(Polygon(ring)) polygon_list.append(Polygon(ring))
return MultiPolygon(polygon_list) return MultiPolygon(polygon_list)
class DBGeometry(TypeDecorator):
impl = LargeBinary
cache_ok = True
def process_bind_param(self, value, dialect):
if isinstance(value, Geometry):
value = to_wkb(value)
return value
def process_result_value(self, value, dialect):
if value is None:
return value
else:
if not isinstance(value, Geometry):
value = from_wkb(value)
return value

50
scl.py
View file

@ -5,17 +5,16 @@ from typing import Optional
import mastodon import mastodon
import requests import requests
import shapely import shapely
import sqlalchemy.types as types
import staticmap import staticmap
import yaml import yaml
from mastodon import Mastodon from mastodon import Mastodon
from PIL import Image, ImageDraw, ImageFont from PIL import Image, ImageDraw, ImageFont
from shapely import Geometry, MultiPolygon, Point, Polygon, from_wkb, to_wkb from shapely import Geometry
from sqlalchemy import create_engine, select from sqlalchemy import create_engine, select
from sqlalchemy.exc import NoResultFound from sqlalchemy.exc import NoResultFound
from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column from sqlalchemy.orm import DeclarativeBase, Mapped, Session, mapped_column
from geospatial import convert_outage_geometry from geospatial import DBGeometry, convert_outage_geometry
post_datetime_format = "%b %e %l:%M %p" post_datetime_format = "%b %e %l:%M %p"
@ -118,16 +117,6 @@ def get_hashtag_string(event) -> str:
return hashtag_string return hashtag_string
def convert_outage_geometry(event) -> MultiPolygon:
assert event["polygons"]["type"] == "polygon"
assert event["polygons"]["hasZ"] is False
assert event["polygons"]["hasM"] is False
polygon_list = []
for ring in event["polygons"]["rings"]:
polygon_list.append(Polygon(ring))
return MultiPolygon(polygon_list)
def do_initial_post( def do_initial_post(
event, event,
event_class, event_class,
@ -272,31 +261,21 @@ Cause: {}
) )
) )
post_result = mastodon_client.status_post( post_result = {"id": "0123"}
status=post_text, # post_result = mastodon_client.status_post(
media_ids=map_media_post, # status=post_text,
visibility="public", # media_ids=map_media_post,
language="en", # visibility="public",
) # language="en",
# )
post_id = post_result["id"] post_id = post_result["id"]
return {"post_id": post_id, "map_media_post_id": map_media_post_id} return {"post_id": post_id, "map_media_post_id": map_media_post_id}
class GeometryWkb(types.TypeDecorator):
impl = types.LargeBinary
cache_ok = True
def process_bind_param(self, value, dialect):
return to_wkb(value)
def process_result_value(self, value, dialect):
return from_wkb(value)
class Base(DeclarativeBase): class Base(DeclarativeBase):
type_annotation_map = { type_annotation_map = {
Geometry: GeometryWkb, Geometry: DBGeometry,
} }
@ -317,10 +296,11 @@ class SclOutage(Base):
max_num_people: Mapped[int] = mapped_column() max_num_people: Mapped[int] = mapped_column()
neighborhood: Mapped[Optional[str]] = mapped_column() neighborhood: Mapped[Optional[str]] = mapped_column()
city: Mapped[Optional[str]] = mapped_column() city: Mapped[Optional[str]] = mapped_column()
outage_geometries: Mapped[Geometry] = mapped_column() outage_geometries: Mapped[Optional[Geometry]] = mapped_column()
geometries_modified: Mapped[Optional[bool]] = mapped_column()
def __repr__(self) -> str: def __repr__(self) -> str:
return f"SclOutage(scl_outage_id={self.scl_outage_id!r}, most_recent_post_id={self.most_recent_post_id!r}, initial_post_id={self.initial_post_id!r}, map_media_post_id={self.map_media_post_id!r}, last_updated_time={self.last_updated_time!r}, no_longer_in_response_time={self.no_longer_in_response_time!r}, start_time={self.start_time!r}, num_people={self.num_people!r}, max_num_people={self.max_num_people!r}, neighborhood={self.neighborhood!r}, city={self.city!r}, outage_geometries={self.outage_geometries!r})" return f"SclOutage(scl_outage_id={self.scl_outage_id!r}, most_recent_post_id={self.most_recent_post_id!r}, initial_post_id={self.initial_post_id!r}, map_media_post_id={self.map_media_post_id!r}, last_updated_time={self.last_updated_time!r}, no_longer_in_response_time={self.no_longer_in_response_time!r}, start_time={self.start_time!r}, num_people={self.num_people!r}, max_num_people={self.max_num_people!r}, neighborhood={self.neighborhood!r}, city={self.city!r}, outage_geometries={self.outage_geometries!r}, geometries_modified={self.geometries_modified!r})"
engine = create_engine("sqlite:///scl.db") engine = create_engine("sqlite:///scl.db")
@ -393,9 +373,9 @@ with Session(engine) as session:
existing_record.max_num_people = event["numPeople"] existing_record.max_num_people = event["numPeople"]
max_event_class = classify_event_size(existing_record.max_num_people) max_event_class = classify_event_size(existing_record.max_num_people)
if existing_record.outage_geometries != outage_geometries: if existing_record.outage_geometries != outage_geometries:
print("updating geometries") print("Geometries modified")
existing_record.outage_geometries = outage_geometries existing_record.outage_geometries = outage_geometries
existing_record.geometries_modified = True
if updated_properties: if updated_properties:
updated_properties.sort() updated_properties.sort()