Skip to content

Commit 66db565

Browse files
authored
Merge pull request #2936 from tkalir/extract-bounding-box-query
Extract bounding box query from models.py
2 parents 4d3d52b + 03470a4 commit 66db565

5 files changed

Lines changed: 288 additions & 284 deletions

File tree

anyway/clusters_calculator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import logging
22
import time
3-
from anyway.models import AccidentMarker
3+
from anyway.marker_bounding_box_query import marker_bounding_box_query
44
from anyway.pymapcluster import calculate_clusters
55

66

77
def retrieve_clusters(**kwargs):
88
start_time = time.time()
9-
result = AccidentMarker.bounding_box_query(is_thin=True, **kwargs)
9+
result = marker_bounding_box_query(is_thin=True, **kwargs)
1010
accident_markers_in_box = result.accident_markers.all()
1111
rsa_markers_in_box = result.rsa_markers.all()
1212
logging.debug("getting cluster data from db took %f seconds" % (time.time() - start_time))

anyway/flask_app.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from anyway.clusters_calculator import retrieve_clusters
2828
from anyway.config import ENTRIES_PER_PAGE
2929
from anyway.constants import CONST
30+
from anyway.marker_bounding_box_query import marker_bounding_box_query
3031
from anyway.infographics_utils import (
3132
get_infographics_mock_data,
3233
get_infographics_data_for_location,
@@ -354,7 +355,7 @@ def markers():
354355
kwargs = get_kwargs()
355356
logging.debug("querying markers in bounding box: %s" % kwargs)
356357
is_thin = kwargs["zoom"] < CONST.MINIMAL_ZOOM
357-
result = AccidentMarker.bounding_box_query(
358+
result = marker_bounding_box_query(
358359
is_thin, yield_per=50, involved_and_vehicles=False, **kwargs
359360
)
360361
accident_markers = result.accident_markers
@@ -443,7 +444,7 @@ def yishuv_symbol_to_name():
443444
def charts_data():
444445
logging.debug("getting charts data")
445446
kwargs = get_kwargs()
446-
accidents, vehicles, involved = AccidentMarker.bounding_box_query(
447+
accidents, vehicles, involved = marker_bounding_box_query(
447448
is_thin=False, yield_per=50, involved_and_vehicles=True, **kwargs
448449
)
449450
accidents_list = [acc.serialize() for acc in accidents]
Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
from sqlalchemy import desc, and_, sql, func, or_
2+
from sqlalchemy.orm import load_only
3+
4+
from anyway.app_and_db import db
5+
from anyway.backend_constants import BE_CONST
6+
from anyway.models import MarkerResult, AccidentMarker, Vehicle, Involved
7+
from anyway.vehicle_type import VehicleType as BE_VehicleType
8+
9+
10+
def marker_bounding_box_query(
11+
is_thin=False, yield_per=None, involved_and_vehicles=False, query_entities=None, **kwargs
12+
) -> MarkerResult:
13+
approx = kwargs.get("approx", True)
14+
accurate = kwargs.get("accurate", True)
15+
page = kwargs.get("page")
16+
per_page = kwargs.get("per_page")
17+
18+
if not kwargs.get("show_markers", True):
19+
return MarkerResult(
20+
accident_markers=db.session.query(AccidentMarker).filter(sql.false()),
21+
rsa_markers=db.session.query(AccidentMarker).filter(sql.false()),
22+
total_records=0,
23+
)
24+
25+
sw_lat = float(kwargs["sw_lat"])
26+
sw_lng = float(kwargs["sw_lng"])
27+
ne_lat = float(kwargs["ne_lat"])
28+
ne_lng = float(kwargs["ne_lng"])
29+
polygon_str = "POLYGON(({0} {1},{0} {3},{2} {3},{2} {1},{0} {1}))".format(
30+
sw_lng, sw_lat, ne_lng, ne_lat
31+
)
32+
33+
if query_entities is not None:
34+
markers = (
35+
db.session.query(AccidentMarker)
36+
.with_entities(*query_entities)
37+
.filter(AccidentMarker.geom.intersects(polygon_str))
38+
.filter(AccidentMarker.created >= kwargs["start_date"])
39+
.filter(AccidentMarker.created <= kwargs["end_date"])
40+
.filter(AccidentMarker.provider_code != BE_CONST.RSA_PROVIDER_CODE)
41+
.order_by(desc(AccidentMarker.created))
42+
)
43+
44+
rsa_markers = (
45+
db.session.query(AccidentMarker)
46+
.with_entities(*query_entities)
47+
.filter(AccidentMarker.geom.intersects(polygon_str))
48+
.filter(AccidentMarker.created >= kwargs["start_date"])
49+
.filter(AccidentMarker.created <= kwargs["end_date"])
50+
.filter(AccidentMarker.provider_code == BE_CONST.RSA_PROVIDER_CODE)
51+
.order_by(desc(AccidentMarker.created))
52+
)
53+
else:
54+
markers = (
55+
db.session.query(AccidentMarker)
56+
.filter(AccidentMarker.geom.intersects(polygon_str))
57+
.filter(AccidentMarker.created >= kwargs["start_date"])
58+
.filter(AccidentMarker.created <= kwargs["end_date"])
59+
.filter(AccidentMarker.provider_code != BE_CONST.RSA_PROVIDER_CODE)
60+
.order_by(desc(AccidentMarker.created))
61+
)
62+
63+
rsa_markers = (
64+
db.session.query(AccidentMarker)
65+
.filter(AccidentMarker.geom.intersects(polygon_str))
66+
.filter(AccidentMarker.created >= kwargs["start_date"])
67+
.filter(AccidentMarker.created <= kwargs["end_date"])
68+
.filter(AccidentMarker.provider_code == BE_CONST.RSA_PROVIDER_CODE)
69+
.order_by(desc(AccidentMarker.created))
70+
)
71+
72+
if not kwargs["show_rsa"]:
73+
rsa_markers = db.session.query(AccidentMarker).filter(sql.false())
74+
if not kwargs["show_accidents"]:
75+
markers = markers.filter(
76+
and_(
77+
AccidentMarker.provider_code != BE_CONST.CBS_ACCIDENT_TYPE_1_CODE,
78+
AccidentMarker.provider_code != BE_CONST.CBS_ACCIDENT_TYPE_3_CODE,
79+
AccidentMarker.provider_code != BE_CONST.UNITED_HATZALA_CODE,
80+
)
81+
)
82+
if yield_per:
83+
markers = markers.yield_per(yield_per)
84+
if accurate and not approx:
85+
markers = markers.filter(AccidentMarker.location_accuracy == 1)
86+
elif approx and not accurate:
87+
markers = markers.filter(AccidentMarker.location_accuracy != 1)
88+
elif not accurate and not approx:
89+
return MarkerResult(
90+
accident_markers=db.session.query(AccidentMarker).filter(sql.false()),
91+
rsa_markers=db.session.query(AccidentMarker).filter(sql.false()),
92+
total_records=0,
93+
)
94+
if not kwargs.get("show_fatal", True):
95+
markers = markers.filter(AccidentMarker.accident_severity != 1)
96+
if not kwargs.get("show_severe", True):
97+
markers = markers.filter(AccidentMarker.accident_severity != 2)
98+
if not kwargs.get("show_light", True):
99+
markers = markers.filter(AccidentMarker.accident_severity != 3)
100+
if kwargs.get("show_urban", 3) != 3:
101+
if kwargs["show_urban"] == 2:
102+
markers = markers.filter(AccidentMarker.road_type >= 1).filter(
103+
AccidentMarker.road_type <= 2
104+
)
105+
elif kwargs["show_urban"] == 1:
106+
markers = markers.filter(AccidentMarker.road_type >= 3).filter(
107+
AccidentMarker.road_type <= 4
108+
)
109+
else:
110+
return MarkerResult(
111+
accident_markers=db.session.query(AccidentMarker).filter(sql.false()),
112+
rsa_markers=rsa_markers,
113+
total_records=None,
114+
)
115+
if kwargs.get("show_intersection", 3) != 3:
116+
if kwargs["show_intersection"] == 2:
117+
markers = markers.filter(AccidentMarker.road_type != 2).filter(
118+
AccidentMarker.road_type != 4
119+
)
120+
elif kwargs["show_intersection"] == 1:
121+
markers = markers.filter(AccidentMarker.road_type != 1).filter(
122+
AccidentMarker.road_type != 3
123+
)
124+
else:
125+
return MarkerResult(
126+
accident_markers=db.session.query(AccidentMarker).filter(sql.false()),
127+
rsa_markers=rsa_markers,
128+
total_records=None,
129+
)
130+
if kwargs.get("show_lane", 3) != 3:
131+
if kwargs["show_lane"] == 2:
132+
markers = markers.filter(AccidentMarker.one_lane >= 2).filter(
133+
AccidentMarker.one_lane <= 3
134+
)
135+
elif kwargs["show_lane"] == 1:
136+
markers = markers.filter(AccidentMarker.one_lane == 1)
137+
else:
138+
return MarkerResult(
139+
accident_markers=db.session.query(AccidentMarker).filter(sql.false()),
140+
rsa_markers=rsa_markers,
141+
total_records=None,
142+
)
143+
144+
if kwargs.get("show_day", 7) != 7:
145+
markers = markers.filter(
146+
func.extract("dow", AccidentMarker.created) == kwargs["show_day"]
147+
)
148+
if kwargs.get("show_holiday", 0) != 0:
149+
markers = markers.filter(AccidentMarker.day_type == kwargs["show_holiday"])
150+
151+
if kwargs.get("show_time", 24) != 24:
152+
if kwargs["show_time"] == 25: # Daylight (6-18)
153+
markers = markers.filter(func.extract("hour", AccidentMarker.created) >= 6).filter(
154+
func.extract("hour", AccidentMarker.created) < 18
155+
)
156+
elif kwargs["show_time"] == 26: # Darktime (18-6)
157+
markers = markers.filter(
158+
(func.extract("hour", AccidentMarker.created) >= 18)
159+
| (func.extract("hour", AccidentMarker.created) < 6)
160+
)
161+
else:
162+
markers = markers.filter(
163+
func.extract("hour", AccidentMarker.created) >= kwargs["show_time"]
164+
).filter(func.extract("hour", AccidentMarker.created) < kwargs["show_time"] + 6)
165+
elif kwargs["start_time"] != 25 and kwargs["end_time"] != 25:
166+
markers = markers.filter(
167+
func.extract("hour", AccidentMarker.created) >= kwargs["start_time"]
168+
).filter(func.extract("hour", AccidentMarker.created) < kwargs["end_time"])
169+
if kwargs.get("weather", 0) != 0:
170+
markers = markers.filter(AccidentMarker.weather == kwargs["weather"])
171+
if kwargs.get("separation", 0) != 0:
172+
markers = markers.filter(AccidentMarker.multi_lane == kwargs["separation"])
173+
if kwargs.get("surface", 0) != 0:
174+
markers = markers.filter(AccidentMarker.road_surface == kwargs["surface"])
175+
if kwargs.get("acctype", 0) != 0:
176+
if kwargs["acctype"] <= 20:
177+
markers = markers.filter(AccidentMarker.accident_type == kwargs["acctype"])
178+
elif kwargs["acctype"] == BE_CONST.BIKE_ACCIDENTS:
179+
markers = markers.filter(
180+
AccidentMarker.vehicles.any(Vehicle.vehicle_type == BE_VehicleType.BIKE.value)
181+
)
182+
if kwargs.get("controlmeasure", 0) != 0:
183+
markers = markers.filter(AccidentMarker.road_control == kwargs["controlmeasure"])
184+
185+
if kwargs.get("case_type", 0) != 0:
186+
markers = markers.filter(AccidentMarker.provider_code == kwargs["case_type"])
187+
188+
if is_thin:
189+
markers = markers.options(load_only("id", "longitude", "latitude"))
190+
191+
if kwargs.get("age_groups"):
192+
age_groups_list = kwargs.get("age_groups").split(",")
193+
if len(age_groups_list) < (BE_CONST.AGE_GROUPS_NUMBER + 1):
194+
markers = markers.filter(
195+
AccidentMarker.involved.any(Involved.age_group.in_(age_groups_list))
196+
)
197+
else:
198+
markers = db.session.query(AccidentMarker).filter(sql.false())
199+
200+
if kwargs.get("light_transportation", False):
201+
age_groups_list = kwargs.get("age_groups").split(",")
202+
LOCATION_ACCURACY_PRECISE_LIST = [1, 3, 4]
203+
markers = markers.filter(
204+
AccidentMarker.location_accuracy.in_(LOCATION_ACCURACY_PRECISE_LIST)
205+
)
206+
INJURED_TYPES = [1, 6, 7]
207+
markers = markers.filter(
208+
or_(
209+
AccidentMarker.involved.any(
210+
and_(
211+
Involved.injured_type.in_(INJURED_TYPES),
212+
Involved.injury_severity >= 1,
213+
Involved.injury_severity <= 3,
214+
Involved.age_group.in_(age_groups_list),
215+
)
216+
),
217+
AccidentMarker.involved.any(
218+
and_(
219+
Involved.vehicle_type == 15,
220+
Involved.injury_severity >= 1,
221+
Involved.injury_severity <= 3,
222+
Involved.age_group.in_(age_groups_list),
223+
)
224+
),
225+
AccidentMarker.involved.any(
226+
and_(
227+
Involved.vehicle_type == 21,
228+
Involved.injury_severity >= 1,
229+
Involved.injury_severity <= 3,
230+
Involved.age_group.in_(age_groups_list),
231+
)
232+
),
233+
AccidentMarker.involved.any(
234+
and_(
235+
Involved.vehicle_type == 23,
236+
Involved.injury_severity >= 1,
237+
Involved.injury_severity <= 3,
238+
Involved.age_group.in_(age_groups_list),
239+
)
240+
),
241+
)
242+
)
243+
244+
if page and per_page:
245+
markers = markers.offset((page - 1) * per_page).limit(per_page)
246+
247+
if involved_and_vehicles:
248+
fetch_markers = kwargs.get("fetch_markers", True)
249+
fetch_vehicles = kwargs.get("fetch_vehicles", True)
250+
fetch_involved = kwargs.get("fetch_involved", True)
251+
markers_ids = [marker.id for marker in markers]
252+
markers = None
253+
vehicles = None
254+
involved = None
255+
if fetch_markers:
256+
markers = db.session.query(AccidentMarker).filter(
257+
AccidentMarker.id.in_(markers_ids)
258+
)
259+
if fetch_vehicles:
260+
vehicles = db.session.query(Vehicle).filter(Vehicle.accident_id.in_(markers_ids))
261+
if fetch_involved:
262+
involved = db.session.query(Involved).filter(Involved.accident_id.in_(markers_ids))
263+
result = (
264+
markers.all() if markers is not None else [],
265+
vehicles.all() if vehicles is not None else [],
266+
involved.all() if involved is not None else [],
267+
)
268+
return MarkerResult(
269+
accident_markers=result,
270+
rsa_markers=db.session.query(AccidentMarker).filter(sql.false()),
271+
total_records=len(result),
272+
)
273+
else:
274+
return MarkerResult(
275+
accident_markers=markers, rsa_markers=rsa_markers, total_records=None
276+
)

0 commit comments

Comments
 (0)