Skip to content

Commit a3d023e

Browse files
committed
feat(filter): add filtration classes and cronjob
1 parent ae60954 commit a3d023e

File tree

16 files changed

+265
-62
lines changed

16 files changed

+265
-62
lines changed

alert_system/admin.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
from django.contrib import admin
22

3-
from .models import Connector, StacItems, EligibleItems
3+
from .models import Connector, EligibleItems, StacItems
44

55

66
@admin.register(Connector)
@@ -16,6 +16,7 @@ class EventAdmin(admin.ModelAdmin):
1616
readonly_fields = ("connector",)
1717
search_fields = ("stac_id",)
1818

19+
1920
@admin.register(EligibleItems)
2021
class EligibleAdmin(admin.ModelAdmin):
2122
list_display = ("stac_id", "created_at", "collection")

alert_system/extraction/base_extraction.py

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import logging
22
from datetime import datetime, timedelta, timezone
3-
from token import OP
43
from typing import Dict, Generator, Optional
54

65
import httpx
@@ -20,9 +19,7 @@ class BaseExtractionClass:
2019

2120
def __init__(self, connector: Connector):
2221
if not self.event_endpoint:
23-
raise NotImplementedError(
24-
f"{self.__class__.__name__} must define event_endpoint, "
25-
)
22+
raise NotImplementedError(f"{self.__class__.__name__} must define event_endpoint, ")
2623
self.connector = connector
2724
self.base_url = connector.source_url.rstrip("/")
2825

@@ -157,7 +154,7 @@ def process_hazard_items(self, stac_obj: StacItems) -> None:
157154
if not self.hazard_endpoint:
158155
return
159156
try:
160-
hazard_features = self._fetch_items(self.hazard_endpoint,"filter_hazard", stac_obj.correlation_id)
157+
hazard_features = self._fetch_items(self.hazard_endpoint, "filter_hazard", stac_obj.correlation_id)
161158
except Exception as e:
162159
logger.error(f"Failed to fetch hazards for event {stac_obj.stac_id}: {e}")
163160
raise

alert_system/extraction/gdacs_cyclone.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from alert_system.extraction.base_extraction import BaseExtractionClass
22

3+
34
class GdacsCycloneExtraction(BaseExtractionClass):
45
event_endpoint = "/gdacs-events/items"
56
hazard_endpoint = "/gdacs-hazards/items"
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
from alert_system.extraction.base_extraction import BaseExtractionClass
22

3+
34
class GdacsFloodExtraction(BaseExtractionClass):
45
event_endpoint = "/gdacs-events/items"
56
hazard_endpoint = "/gdacs-hazards/items"
67
impact_endpoint = "/gdacs-impacts/items"
7-

alert_system/extraction/usgs_earthquake.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from alert_system.extraction.base_extraction import BaseExtractionClass
22

3+
34
class USGSEarthquakeExtraction(BaseExtractionClass):
45
event_endpoint = "/usgs-events/items"
56
hazard_endpoint = "/usgs-hazards/items"

alert_system/filters/__init__.py

Whitespace-only changes.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
from abc import ABC
2+
from typing import Dict
3+
4+
from alert_system.models import StacItems
5+
6+
7+
class BaseFilter(ABC):
8+
9+
hazard_threshold: Dict
10+
impact_threshold: Dict
11+
12+
def __init__(self, stac_obj: StacItems):
13+
self.item = stac_obj
14+
15+
def is_hazard_eligible(self) -> bool:
16+
"""Return True if hazard passes filters."""
17+
return (
18+
self.item.severity_value > self.hazard_threshold["severity_value"]
19+
and self.item.severity_label == self.hazard_threshold["severity_label"]
20+
)
21+
22+
def is_impact_eligible(self) -> bool:
23+
"""Return True if impact passes filters."""
24+
key = (self.item.category, self.item.type)
25+
threshold = self.impact_threshold.get(key)
26+
if threshold is None:
27+
return False
28+
return self.item.value >= threshold
29+
30+
def is_eligible(self) -> bool:
31+
if self.item.collection == StacItems.CollectionType.IMPACT:
32+
return self.is_impact_eligible()
33+
elif self.item.collection == StacItems.CollectionType.HAZARD:
34+
return self.is_hazard_eligible()
35+
return True
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
from .base_filter import BaseFilter
2+
3+
4+
class GdacsCycloneFilter(BaseFilter):
5+
6+
impact_threshold = {
7+
("people", "death"): 1,
8+
("people", "injured"): 10,
9+
("people", "missing"): 1,
10+
}
11+
12+
hazard_threshold = {
13+
"severity_value": 5,
14+
"severity_label": "Green",
15+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from .base_filter import BaseFilter
2+
3+
4+
class GdacsFloodFilter(BaseFilter):
5+
impact_threshold = {
6+
("people", "death"): 1,
7+
("people", "injured"): 10,
8+
("people", "missing"): 1,
9+
}
10+
11+
hazard_threshold = {
12+
"severity_value": 0,
13+
"severity_label": "Green",
14+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
from .base_filter import BaseFilter
2+
3+
4+
class USGSEarthquakeFilter(BaseFilter):
5+
impact_threshold = {
6+
("people", "death"): 1,
7+
("people", "injured"): 10,
8+
("people", "missing"): 1,
9+
}
10+
11+
hazard_threshold = {
12+
"severity_value": 5,
13+
"severity_label": "Green",
14+
}

0 commit comments

Comments
 (0)