Repository: data-for-change/anyway

Issue:
Standard Sadna README



Discussion:
Added detailed for vagrant provisioning etc. to the README
@omribahumi did you change something
@galraij added a link to open knesset, hope this makes us better Hasadna residents
Still some promises for more info as a "soon" remark


Resolving patch:
diff --git a/anyway/backend_constants.py b/anyway/backend_constants.py
--- a/anyway/backend_constants.py
+++ b/anyway/backend_constants.py
@@ -211,3 +211,28 @@ def labels(cls):
             DriverType.PRIVATE_VEHICLE_DRIVER: "private_vehicle_driver",
             DriverType.OTHER_DRIVER: "other_driver",
         }
+
+class InjuredType(LabeledCode):
+    PEDESTRIAN = 1
+    DRIVER_FOUR_WHEELS_AND_ABOVE = 2
+    PASSENGER_FOUR_WHEELS_AND_ABOVE = 3
+    DRIVER_MOTORCYCLE = 4
+    PASSENGER_MOTORCYCLE = 5
+    DRIVER_BICYCLE = 6
+    PASSENGER_BICYCLE = 7
+    DRIVER_UNKNOWN_VEHICLE = 8
+    PASSENGER_UNKNOWN_VEHICLE = 9
+
+    @classmethod
+    def labels(cls):
+        return {
+            InjuredType.PEDESTRIAN:"Pedestrian",
+            InjuredType.DRIVER_FOUR_WHEELS_AND_ABOVE: "Driver of a vehicle with 4 wheel or more",
+            InjuredType.PASSENGER_FOUR_WHEELS_AND_ABOVE: "Passenger of a vehicle with 4 wheel or more",
+            InjuredType.DRIVER_MOTORCYCLE: "Motorcycle driver",
+            InjuredType.PASSENGER_MOTORCYCLE: "Motorcycle passenger",
+            InjuredType.DRIVER_BICYCLE: "Bicycle driver",
+            InjuredType.PASSENGER_BICYCLE: "Bicycle passenger",
+            InjuredType.DRIVER_UNKNOWN_VEHICLE: "Driver of an unknown vehicle",
+            InjuredType.PASSENGER_UNKNOWN_VEHICLE: "Passenger of an unknown vehicle"
+        }
\ No newline at end of file
diff --git a/anyway/infographics_utils.py b/anyway/infographics_utils.py
--- a/anyway/infographics_utils.py
+++ b/anyway/infographics_utils.py
@@ -18,11 +18,14 @@
 from sqlalchemy import func, distinct, literal_column, case
 from sqlalchemy import cast, Numeric
 from sqlalchemy import desc
+from sqlalchemy import or_
+from sqlalchemy.sql.elements import and_
+
 
 # noinspection PyProtectedMember
 from flask_babel import _
 from anyway.backend_constants import (
-    BE_CONST, LabeledCode, InjurySeverity, AccidentSeverity, DriverType, AccidentType
+    BE_CONST, InjuredType, LabeledCode, InjurySeverity, AccidentSeverity, DriverType, AccidentType
 )
 from anyway.models import NewsFlash, AccidentMarkerView, InvolvedMarkerView, VehicleMarkerView
 from anyway.parsers import resolution_dict
@@ -1118,91 +1121,70 @@ def localize_items(request_params: RequestParams, items: Dict) -> Dict:
 
 
 @register
-class InjuredAccidentsWithPedestriansWidget(SubUrbanWidget):
+class InjuredAccidentsWithPedestriansWidget(UrbanWidget):
     name: str = "injured_accidents_with_pedestrians"
 
+    def validate_parameters(self, yishuv_name, street1_hebrew):
+        # TODO: validate each parameter and display message accordingly
+        return yishuv_name is not None and \
+            street1_hebrew is not None and  \
+            self.request_params.years_ago is not None
+
+    def convert_to_dict(self, query_results):
+        res = {}
+
+        for query_result in query_results:
+            if query_result.injury_severity not in res:
+                res[query_result.injury_severity] = {}
+            if query_result.accident_year not in res[query_result.injury_severity]:
+                res[query_result.injury_severity][query_result.accident_year] = 0
+
+            res[query_result.injury_severity][query_result.accident_year] += query_result.count
+
+        return res
+
     def __init__(self, request_params: RequestParams):
         super().__init__(request_params, type(self).name)
         self.rank = 18
-        self.text = {"title": "נפגעים הולכי רגל ברחוב ז׳בוטינסקי, פתח תקווה"}
-
-    @staticmethod
-    def is_in_cache() -> bool:
-        return False
 
     def generate_items(self) -> None:
-        self.items = (
-            InjuredAccidentsWithPedestriansWidget.injured_accidents_with_pedestrians_mock_data()
-        )
+        try:
+            yishuv_name = self.request_params.location_info.get('yishuv_name')
+            street1_hebrew = self.request_params.location_info.get('street1_hebrew')
+
+            if not self.validate_parameters(yishuv_name, street1_hebrew):
+                logging.exception(f"Could not validate parameters for {NewsFlash} : {self.request_params.news_flash_obj.id}")
+                return None
+
+            query = db.session.query(InvolvedMarkerView)    \
+                .with_entities(InvolvedMarkerView.accident_year,    \
+                    InvolvedMarkerView.injury_severity, \
+                    func.count().label('count'))  \
+                .filter(InvolvedMarkerView.accident_yishuv_name == yishuv_name)\
+                .filter(InvolvedMarkerView.injury_severity.in_([InjurySeverity.KILLED.value, InjurySeverity.SEVERE_INJURED.value, InjurySeverity.LIGHT_INJURED.value]))   \
+                .filter(InvolvedMarkerView.injured_type == InjuredType.PEDESTRIAN.value)   \
+                .filter(or_(InvolvedMarkerView.street1_hebrew == street1_hebrew, InvolvedMarkerView.street2_hebrew == street1_hebrew))    \
+                .filter(and_(InvolvedMarkerView.accident_timestamp >= self.request_params.start_time, InvolvedMarkerView.accident_timestamp <= self.request_params.end_time)) \
+                .group_by(InvolvedMarkerView.accident_year, InvolvedMarkerView.injury_severity)
 
-    @staticmethod
-    def injured_accidents_with_pedestrians_mock_data():  # Temporary for Frontend
-        return [
-            {
-                "year": 2009,
-                "light_injury_severity_text": "פצוע קל",
-                "light_injury_severity_count": 12,
-                "severe_injury_severity_text": "פצוע קשה",
-                "severe_injury_severity_count": 3,
-                "killed_injury_severity_text": "הרוג",
-                "killed_injury_severity_count": 0,
-            },
-            {
-                "year": 2010,
-                "light_injury_severity_text": "פצוע קל",
-                "light_injury_severity_count": 24,
-                "severe_injury_severity_text": "פצוע קשה",
-                "severe_injury_severity_count": 0,
-                "killed_injury_severity_text": "הרוג",
-                "killed_injury_severity_count": 1,
-            },
-            {
-                "year": 2011,
-                "light_injury_severity_text": "פצוע קל",
-                "light_injury_severity_count": 9,
-                "severe_injury_severity_text": "פצוע קשה",
-                "severe_injury_severity_count": 2,
-                "killed_injury_severity_text": "הרוג",
-                "killed_injury_severity_count": 1,
-            },
-            {
-                "year": 2012,
-                "light_injury_severity_text": "פצוע קל",
-                "light_injury_severity_count": 21,
-                "severe_injury_severity_text": "פצוע קשה",
-                "severe_injury_severity_count": 2,
-                "killed_injury_severity_text": "הרוג",
-                "killed_injury_severity_count": 4,
-            },
-            {
-                "year": 2013,
-                "light_injury_severity_text": "פצוע קל",
-                "light_injury_severity_count": 21,
-                "severe_injury_severity_text": "פצוע קשה",
-                "severe_injury_severity_count": 2,
-                "killed_injury_severity_text": "הרוג",
-                "killed_injury_severity_count": 4,
-            },
-            {
-                "year": 2014,
-                "light_injury_severity_text": "פצוע קל",
-                "light_injury_severity_count": 10,
-                "severe_injury_severity_text": "פצוע קשה",
-                "severe_injury_severity_count": 0,
-                "killed_injury_severity_text": "הרוג",
-                "killed_injury_severity_count": 1,
-            },
-            {
-                "year": 2015,
-                "light_injury_severity_text": "פצוע קל",
-                "light_injury_severity_count": 13,
-                "severe_injury_severity_text": "פצוע קשה",
-                "severe_injury_severity_count": 2,
-                "killed_injury_severity_text": "הרוג",
-                "killed_injury_severity_count": 0,
-            },
-        ]
+            self.items = add_empty_keys_to_gen_two_level_dict(
+                self.convert_to_dict(query.all()),
+                InjurySeverity.codes(),
+                list(range(self.request_params.start_time.year,
+                           self.request_params.end_time.year + 1))
+            )
 
+        except Exception as e:
+            logging.error(f"InjuredAccidentsWithPedestriansWidget.generate_items(): {e}")
+            raise Exception(e)
+
+    @staticmethod
+    def localize_items(request_params: RequestParams, items: Dict) -> Dict:
+        items["data"]["text"] = {
+            "title": f"נפגעים הולכי רגל ב- {get_news_flash_location_text(request_params.news_flash_obj)}",
+            "labels": gen_entity_labels(InjurySeverity)
+        }
+        return items
 
 @register
 class AccidentSeverityByCrossLocationWidget(SubUrbanWidget):


Test patch: